2 * Copyright (c) 2007-2015 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecureObjectSync/SOSPeerInfoDER.h>
25 #include <Security/SecureObjectSync/SOSCloudCircle.h>
26 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27 #include <Security/SecureObjectSync/SOSInternal.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecEntitlements.h>
32 #include <Security/SecInternal.h>
33 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
34 #include <Security/SecPolicyInternal.h>
35 #include <Security/SecTask.h>
36 #include <Security/SecuritydXPC.h>
37 #include <securityd/OTATrustUtilities.h>
38 #include <securityd/SOSCloudCircleServer.h>
39 #include <securityd/SecItemBackupServer.h>
40 #include <securityd/SecItemServer.h>
41 #include <securityd/SecLogSettingsServer.h>
42 #include <securityd/SecOTRRemote.h>
43 #include <securityd/SecTrustServer.h>
44 #include <securityd/SecTrustStoreServer.h>
45 #include <securityd/iCloudTrace.h>
46 #include <securityd/spi.h>
47 #include <utilities/SecCFError.h>
48 #include <utilities/SecCFWrappers.h>
49 #include <utilities/SecDb.h>
50 #include <utilities/SecIOFormat.h>
51 #include <utilities/SecXPCError.h>
52 #include <utilities/debugging.h>
53 #include <utilities/SecInternalReleasePriv.h>
55 #include <AssertMacros.h>
56 #include <CoreFoundation/CFXPCBridge.h>
57 #include <CoreFoundation/CoreFoundation.h>
58 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
59 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
60 #include <MobileKeyBag/MobileKeyBag.h>
61 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
63 #include <bsm/libbsm.h>
64 #include <ipc/securityd_client.h>
65 #include <libkern/OSAtomic.h>
66 #include <mach/mach.h>
67 #include <mach/message.h>
70 #include <sys/queue.h>
71 #include <sys/sysctl.h>
73 #include <xpc/private.h>
76 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
77 #include <Security/SecTaskPriv.h>
80 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
81 CFStringRef entitlement
)
83 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
85 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
93 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
94 CFStringRef entitlement
)
96 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
99 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
100 CFIndex ix
, count
= CFArrayGetCount(value
);
101 for (ix
= 0; ix
< count
; ++ix
) {
102 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
103 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
118 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
119 return SecTaskCopyStringForEntitlement(task
,
120 kSecEntitlementApplicationIdentifier
);
123 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
124 return SecTaskCopyArrayOfStringsForEntitlement(task
,
125 kSecEntitlementAssociatedDomains
);
128 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
129 CFMutableArrayRef groups
= NULL
;
130 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
131 kSecEntitlementKeychainAccessGroups
);
132 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
133 kSecEntitlementAppleSecurityApplicationGroups
);
134 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
135 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
136 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
137 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
138 if ((appID
|| asagLen
) && !SecTaskEntitlementsValidated(task
)) {
139 CFReleaseNull(appID
);
143 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
145 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
);
147 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
149 CFArrayAppendValue(groups
, appID
);
151 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
152 #if TARGET_IPHONE_SIMULATOR
154 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
155 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
159 CFReleaseSafe(appID
);
160 CFReleaseSafe(keychainAccessGroups
);
161 CFReleaseSafe(appleSecurityApplicationGroups
);
165 static pthread_key_t taskThreadKey
;
166 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
167 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
168 if (taskRef
== NULL
) {
169 secerror("MISSING keychain entitlements: no stored taskRef found");
173 CFErrorRef error
= NULL
;
174 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
175 kSecEntitlementApplicationIdentifier
,
176 kSecEntitlementKeychainAccessGroups
,
177 kSecEntitlementAppleSecurityApplicationGroups
,
179 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
180 CFRelease(entitlementNames
);
182 if (rawEntitlements
== NULL
) {
183 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
184 CFReleaseSafe(error
);
185 __security_simulatecrash(CFSTR("failed to read keychain client entitlement(s)"), __sec_exception_code_MissingEntitlements
);
189 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
190 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
191 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
192 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
194 __security_simulatecrash(CFSTR("keychain entitlement(s) missing"), __sec_exception_code_MissingEntitlements
);
196 CFReleaseSafe(newAccessGroups
);
197 CFReleaseSafe(rawEntitlements
);
200 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
201 CFStringRef entitlement
) {
202 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
206 CFTypeID canModifyType
= CFGetTypeID(canModify
);
207 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
208 CFRelease(canModify
);
212 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
213 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
215 if (label_utf8
) { // Anything we would do here requires a user label
216 size_t password_length
= 0;
217 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
219 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
220 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
222 action(user_label
, user_password
);
224 CFReleaseNull(user_password
);
225 CFReleaseNull(user_label
);
229 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
230 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
232 if (label_utf8
) { // Anything we would do here requires a user label
233 size_t password_length
= 0;
234 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
235 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
237 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
238 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
239 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
241 action(user_label
, user_password
, dsid
);
244 CFReleaseNull(user_password
);
245 CFReleaseNull(user_label
);
249 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
250 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
251 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
252 secnotice("views", "Action Code Raw is %d", (int) number
);
253 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
255 action(user_label
, number
);
256 CFReleaseNull(user_label
);
259 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
262 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
266 xpc_dictionary_set_value(message
, key
, xpc_chain
);
267 xpc_release(xpc_chain
);
271 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
273 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
275 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
278 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
280 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
285 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
286 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
287 if (!xpc_certificates
)
288 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
289 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
290 return *certificates
;
293 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
294 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
295 if (!xpc_certificates
) {
296 *certificates
= NULL
;
299 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
300 return *certificates
;
303 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
304 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
310 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
311 return *policies
!= NULL
;
314 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
315 SecTrustStoreRef ts
= NULL
;
316 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
318 ts
= SecTrustStoreForDomainName(domain
, error
);
324 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
325 *pvalue
= xpc_dictionary_get_double(message
, key
);
326 if (*pvalue
== NAN
) {
327 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
332 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
333 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
336 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
337 CFDataRef data
= NULL
;
339 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
341 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
344 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
349 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
350 CFMutableArrayRef data_array
= NULL
;
351 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
352 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
353 size_t count
= xpc_array_get_count(xpc_data_array
);
354 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
355 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
358 for (ix
= 0; ix
< count
; ++ix
) {
359 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
361 CFRelease(data_array
);
364 CFArraySetValueAtIndex(data_array
, ix
, data
);
372 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
373 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
374 if (!xpc_data_array
) {
379 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
380 return *data_array
!= NULL
;
383 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
384 CFErrorRef error
= NULL
;
385 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
386 CFSetRef retval
= NULL
;
387 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
388 CFReleaseNull(error
);
393 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
395 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
396 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
397 xpc_release(xpc_array
);
399 CFReleaseNull(cf_array
);
403 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
406 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
408 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
409 xpc_release(xpc_array
);
414 CFReleaseNull(cf_array
);
419 EntitlementMissing(enum SecXPCOperation op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
421 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription(op
), clientTask
, entitlement
);
427 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
428 xpc_type_t type
= xpc_get_type(event
);
429 __block CFErrorRef error
= NULL
;
430 xpc_object_t xpcError
= NULL
;
431 xpc_object_t replyMessage
= NULL
;
432 SecTaskRef clientTask
= NULL
;
433 CFDataRef clientAuditToken
= NULL
;
434 CFArrayRef accessGroups
= NULL
;
435 CFArrayRef domains
= NULL
;
437 secdebug("serverxpc", "entering");
438 if (type
== XPC_TYPE_DICTIONARY
) {
439 // TODO: Find out what we're dispatching.
440 replyMessage
= xpc_dictionary_create_reply(event
);
442 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
445 audit_token_t auditToken
= {};
446 xpc_connection_get_audit_token(connection
, &auditToken
);
448 clientTask
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
449 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
450 pthread_setspecific(taskThreadKey
, clientTask
);
451 accessGroups
= SecTaskCopyAccessGroups(clientTask
);
452 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
453 domains
= SecTaskCopySharedWebCredentialDomains(clientTask
);
456 // TODO: change back to secdebug
457 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
460 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
461 // Refer to rdar://problem/18615626&18616300 for more details.
462 int64_t minimumDirtyInterval
= (int64_t) (2 * NSEC_PER_SEC
);
463 xpc_transaction_begin();
464 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, minimumDirtyInterval
), dispatch_get_main_queue(), ^{
465 xpc_transaction_end();
469 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
470 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
471 (clientTask
&& SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementKeychainCloudCircle
));
473 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
474 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
476 if (!hasEntitlement
) {
477 CFErrorRef entitlementError
= NULL
;
478 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementKeychainCloudCircle
);
479 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
480 CFReleaseSafe(entitlementError
);
486 case sec_item_add_id
:
488 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
490 CFTypeRef result
= NULL
;
491 if (_SecItemAdd(query
, accessGroups
, &result
, &error
) && result
) {
492 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
499 case sec_item_copy_matching_id
:
501 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
503 CFTypeRef result
= NULL
;
504 if (_SecItemCopyMatching(query
, accessGroups
, &result
, &error
) && result
) {
505 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
512 case sec_item_update_id
:
514 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
516 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
517 if (attributesToUpdate
) {
518 bool result
= _SecItemUpdate(query
, attributesToUpdate
, accessGroups
, &error
);
519 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
520 CFRelease(attributesToUpdate
);
526 case sec_item_delete_id
:
528 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
530 bool result
= _SecItemDelete(query
, accessGroups
, &error
);
531 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
536 case sec_trust_store_contains_id
:
538 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
540 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
543 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
544 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
550 case sec_trust_store_set_trust_settings_id
:
552 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementModifyAnchorCertificates
)) {
553 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
555 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
557 CFTypeRef trustSettingsDictOrArray
= NULL
;
558 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
559 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
560 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
561 CFReleaseSafe(trustSettingsDictOrArray
);
563 CFRelease(certificate
);
567 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementModifyAnchorCertificates
, &error
);
571 case sec_trust_store_remove_certificate_id
:
573 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementModifyAnchorCertificates
)) {
574 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
576 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
578 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
579 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
584 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementModifyAnchorCertificates
, &error
);
588 case sec_delete_all_id
:
589 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
591 case sec_trust_evaluate_id
:
593 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
594 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
596 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
597 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
598 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
599 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
600 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
601 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
602 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
603 // If we have no error yet, capture connection and reply in block and properly retain them.
604 xpc_retain(connection
);
605 CFRetainSafe(clientTask
);
606 CFRetainSafe(clientAuditToken
);
608 // Clear replyMessage so we don't send a synchronous reply.
609 xpc_object_t asyncReply
= replyMessage
;
612 SecTrustServerEvaluateBlock(clientAuditToken
,
613 certificates
, anchors
, anchorsOnly
, policies
, responses
, scts
, trustedLogs
, verifyTime
, accessGroups
,
614 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
615 // Send back reply now
617 CFRetain(replyError
);
619 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
620 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
621 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
622 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
625 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
626 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
628 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
629 xpc_release(xpcReplyError
);
631 CFRelease(replyError
);
633 secdebug("ipc", "%@ %@ responding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
636 xpc_connection_send_message(connection
, asyncReply
);
637 xpc_release(asyncReply
);
638 xpc_release(connection
);
639 CFReleaseSafe(clientTask
);
640 CFReleaseSafe(clientAuditToken
);
643 CFReleaseSafe(policies
);
644 CFReleaseSafe(anchors
);
645 CFReleaseSafe(certificates
);
646 CFReleaseSafe(responses
);
648 CFReleaseSafe(trustedLogs
);
651 case sec_keychain_backup_id
:
653 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
654 CFDataRef keybag
= NULL
, passcode
= NULL
;
655 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
656 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
657 CFDataRef backup
= _SecServerKeychainBackup(keybag
, passcode
, &error
);
659 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
662 CFReleaseSafe(passcode
);
664 CFReleaseSafe(keybag
);
667 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
671 case sec_keychain_restore_id
:
673 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
674 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
676 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
678 CFDataRef passcode
= NULL
;
679 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
680 bool result
= _SecServerKeychainRestore(backup
, keybag
, passcode
, &error
);
681 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
682 CFReleaseSafe(passcode
);
689 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
693 case sec_keychain_sync_update_message_id
:
695 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
697 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
698 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
699 CFReleaseNull(result
);
701 CFReleaseNull(updates
);
704 case sec_keychain_backup_syncable_id
:
706 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
708 CFDictionaryRef oldbackup
= NULL
;
709 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
710 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
712 CFDataRef passcode
= NULL
;
713 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
714 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
716 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
717 CFRelease(newbackup
);
719 CFReleaseSafe(passcode
);
723 CFReleaseSafe(oldbackup
);
726 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
730 case sec_keychain_restore_syncable_id
:
732 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
734 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
736 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
738 CFDataRef passcode
= NULL
;
739 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
740 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
741 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
742 CFReleaseSafe(passcode
);
749 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
753 case sec_item_backup_copy_names_id
:
755 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
756 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
757 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
758 CFReleaseSafe(names
);
760 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
764 case sec_item_backup_handoff_fd_id
:
766 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
767 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
770 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
771 CFRelease(backupName
);
773 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
777 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
781 case sec_item_backup_set_confirmed_manifest_id
:
783 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
784 CFDataRef keybagDigest
= NULL
;
785 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
786 CFDataRef manifest
= NULL
;
787 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
788 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
790 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
791 CFRelease(backupName
);
792 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
794 CFReleaseSafe(manifest
);
796 CFReleaseNull(keybagDigest
);
799 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
803 case sec_item_backup_restore_id
:
805 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
807 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
809 CFStringRef peerID
= NULL
;
810 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
811 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
813 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
815 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
817 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
824 CFReleaseSafe(peerID
);
826 CFRelease(backupName
);
828 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
830 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
834 case sec_ota_pki_asset_version_id
:
836 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
837 SecOTAPKIGetCurrentAssetVersion(&error
));
840 case sec_add_shared_web_credential_id
:
842 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
844 CFTypeRef result
= NULL
;
845 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
846 if (_SecAddSharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
847 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
850 CFReleaseSafe(appID
);
855 case sec_copy_shared_web_credential_id
:
857 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
859 CFTypeRef result
= NULL
;
860 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
861 if (_SecCopySharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
862 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
865 CFReleaseSafe(appID
);
870 case sec_get_log_settings_id
:
872 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
874 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
876 CFReleaseSafe(currentList
);
879 case sec_set_xpc_log_settings_id
:
881 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
883 SecSetXPCLogSettings_Server(newSettings
, &error
);
885 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
886 CFReleaseNull(newSettings
);
889 case sec_set_circle_log_settings_id
:
891 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
893 SecSetCircleLogSettings_Server(newSettings
, &error
);
895 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
896 CFReleaseNull(newSettings
);
899 case sec_otr_session_create_remote_id
:
901 CFDataRef publicPeerId
= NULL
;
902 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
903 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
905 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
906 CFRelease(otrSession
);
908 CFReleaseSafe(publicPeerId
);
912 case sec_otr_session_process_packet_remote_id
:
914 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
915 bool readyForMessages
= false;
916 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
917 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
918 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
920 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
921 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
922 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
923 CFRelease(outputSessionData
);
924 CFRelease(outputPacket
);
926 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
928 CFReleaseSafe(inputPacket
);
930 CFReleaseSafe(sessionData
);
934 case kSecXPCOpTryUserCredentials
:
935 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
936 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
937 SOSCCTryUserCredentials_Server(label
, password
, &error
));
940 case kSecXPCOpSetUserCredentials
:
941 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
942 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
943 SOSCCSetUserCredentials_Server(label
, password
, &error
));
946 case kSecXPCOpSetUserCredentialsAndDSID
:
947 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
948 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
949 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
953 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
954 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
955 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
958 case kSecXPCOpViewSet
:
960 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
961 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
962 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
963 CFReleaseNull(enabledViews
);
964 CFReleaseNull(disabledViews
);
967 case kSecXPCOpSecurityProperty
:
968 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
969 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
970 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
973 case kSecXPCOpCanAuthenticate
:
974 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
975 SOSCCCanAuthenticate_Server(&error
));
977 case kSecXPCOpPurgeUserCredentials
:
978 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
979 SOSCCPurgeUserCredentials_Server(&error
));
981 case kSecXPCOpDeviceInCircle
:
982 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
983 SOSCCThisDeviceIsInCircle_Server(&error
));
985 case kSecXPCOpRequestToJoin
:
986 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
987 SOSCCRequestToJoinCircle_Server(&error
));
989 case kSecXPCOpRequestToJoinAfterRestore
:
990 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
991 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
993 case kSecXPCOpRequestEnsureFreshParameters
:
994 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
995 SOSCCRequestEnsureFreshParameters_Server(&error
));
997 case kSecXPCOpGetAllTheRings
:
999 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
1000 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
1001 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1002 xpc_release(xpc_dictionary
);
1005 case kSecXPCOpApplyToARing
:
1007 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1008 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
1009 CFReleaseNull(ringName
);
1012 case kSecXPCOpWithdrawlFromARing
:
1014 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1015 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
1016 CFReleaseNull(ringName
);
1019 case kSecXPCOpRingStatus
:
1021 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1022 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
1023 CFReleaseNull(ringName
);
1026 case kSecXPCOpEnableRing
:
1028 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1029 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
1030 CFReleaseNull(ringName
);
1033 case kSecXPCOpRequestDeviceID
:
1035 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
1037 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
1039 CFReleaseNull(deviceID
);
1042 case kSecXPCOpSetDeviceID
:
1044 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1045 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1049 case kSecXPCOpHandleIDSMessage
:
1051 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1052 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1057 case kSecXPCOpSendIDSMessage
:
1059 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1060 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1061 CFReleaseNull(message
);
1064 case kSecXPCOpPingTest
:
1066 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1067 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1068 CFReleaseNull(message
);
1071 case kSecXPCOpIDSDeviceID
:
1073 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1076 case kSecXPCOpAccountSetToNew
:
1077 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1079 case kSecXPCOpResetToOffering
:
1080 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1081 SOSCCResetToOffering_Server(&error
));
1083 case kSecXPCOpResetToEmpty
:
1084 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1085 SOSCCResetToEmpty_Server(&error
));
1087 case kSecXPCOpRemoveThisDeviceFromCircle
:
1088 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1089 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1091 case kSecXPCOpRemovePeersFromCircle
:
1093 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfos
, &error
);
1094 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1095 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1096 CFReleaseNull(applicants
);
1099 case kSecXPCOpLoggedOutOfAccount
:
1100 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1101 SOSCCLoggedOutOfAccount_Server(&error
));
1103 case kSecXPCOpBailFromCircle
:
1105 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1106 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1107 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1110 case kSecXPCOpAcceptApplicants
:
1112 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1113 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1114 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1115 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1116 CFReleaseSafe(applicants
);
1119 case kSecXPCOpRejectApplicants
:
1121 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1122 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1123 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1124 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1125 CFReleaseSafe(applicants
);
1128 case kSecXPCOpSetNewPublicBackupKey
:
1130 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
1131 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1132 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1133 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1134 CFReleaseNull(peerInfo
);
1136 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1137 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1138 xpc_release(xpc_object
);
1140 CFReleaseNull(peerInfoData
);
1141 CFReleaseSafe(publicBackupKey
);
1144 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
1148 case kSecXPCOpSetBagForAllSlices
:
1150 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementRestoreKeychain
)) {
1151 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1152 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1153 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1154 CFReleaseSafe(backupSlice
);
1156 EntitlementMissing(((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementRestoreKeychain
, &error
);
1160 case kSecXPCOpCopyApplicantPeerInfo
:
1161 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1162 SOSCCCopyApplicantPeerInfo_Server(&error
),
1165 case kSecXPCOpCopyValidPeerPeerInfo
:
1166 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1167 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1170 case kSecXPCOpValidateUserPublic
:
1172 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1173 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1176 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1177 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1178 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1181 case kSecXPCOpCopyGenerationPeerInfo
:
1182 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1183 SOSCCCopyGenerationPeerInfo_Server(&error
));
1185 case kSecXPCOpCopyRetirementPeerInfo
:
1186 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1187 SOSCCCopyRetirementPeerInfo_Server(&error
),
1190 case kSecXPCOpCopyViewUnawarePeerInfo
:
1191 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1192 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1195 case kSecXPCOpCopyEngineState
:
1197 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1199 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1200 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1201 xpc_release(xpc_array
);
1203 CFReleaseNull(array
);
1206 case kSecXPCOpCopyPeerPeerInfo
:
1207 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1208 SOSCCCopyPeerPeerInfo_Server(&error
),
1211 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1212 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1213 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1216 case kSecXPCOpCopyMyPeerInfo
:
1218 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1219 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1220 CFReleaseNull(peerInfo
);
1222 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1223 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1224 xpc_release(xpc_object
);
1226 CFReleaseNull(peerInfoData
);
1229 case kSecXPCOpGetLastDepartureReason
:
1230 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1231 SOSCCGetLastDepartureReason_Server(&error
));
1233 case kSecXPCOpSetLastDepartureReason
:
1235 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1236 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1237 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1240 case kSecXPCOpProcessSyncWithAllPeers
:
1241 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1242 SOSCCProcessSyncWithAllPeers_Server(&error
));
1244 case soscc_EnsurePeerRegistration_id
:
1245 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1246 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1248 case kSecXPCOpCopyIncompatibilityInfo
:
1250 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1251 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1255 case kSecXPCOpOTAGetEscrowCertificates
:
1257 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1258 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1260 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1261 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1262 xpc_release(xpc_array
);
1264 CFReleaseNull(array
);
1267 case kSecXPCOpOTAPKIGetNewAsset
:
1268 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1269 SecOTAPKISignalNewAsset(&error
));
1271 case kSecXPCOpRollKeys
:
1273 bool force
= xpc_dictionary_get_bool(event
, "force");
1274 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1275 _SecServerRollKeys(force
, &error
));
1278 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1280 CFDataRef cfbytes
= NULL
;
1281 const uint8_t *bytes
= NULL
;
1284 bytes
= xpc_dictionary_get_data(event
,
1285 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1287 SOSCreateError(kSOSErrorBadKey
,
1288 CFSTR("missing autoaccept info"), NULL
, &error
);
1292 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1294 SOSCreateError(kSOSErrorAllocationFailure
,
1295 CFSTR("could not allocate autoaccept info"),
1300 xpc_dictionary_set_bool(replyMessage
,
1302 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1306 case kSecXPCOpWaitForInitialSync
:
1307 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1308 SOSCCWaitForInitialSync_Server(&error
));
1311 case kSecXPCOpCopyYetToSyncViews
:
1313 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1315 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1316 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1317 xpc_release(xpc_array
);
1319 CFReleaseNull(array
);
1322 case kSecXPCOpSetEscrowRecord
:
1324 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1325 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1327 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1329 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1331 CFReleaseNull(escrow_label
);
1334 case kSecXPCOpGetEscrowRecord
:
1336 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1338 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1339 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1340 xpc_release(xpc_dictionary
);
1342 CFReleaseNull(record
);
1345 case kSecXPCOpCheckPeerAvailability
:
1347 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1358 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1359 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1360 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1361 secwarning("Authentication is needed %@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1363 secerror("%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1365 xpcError
= SecCreateXPCObjectWithCFError(error
);
1367 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1369 } else if (replyMessage
) {
1370 secdebug("ipc", "%@ %@ responding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1373 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1374 secerror("%@: returning error: %@", clientTask
, error
);
1375 xpcError
= SecCreateXPCObjectWithCFError(error
);
1376 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1380 xpc_connection_send_message(connection
, replyMessage
);
1381 xpc_release(replyMessage
);
1384 xpc_release(xpcError
);
1385 CFReleaseSafe(error
);
1386 CFReleaseSafe(accessGroups
);
1387 CFReleaseSafe(domains
);
1388 pthread_setspecific(taskThreadKey
, NULL
);
1389 CFReleaseSafe(clientTask
);
1390 CFReleaseSafe(clientAuditToken
);
1393 static void securityd_xpc_init(const char *service_name
)
1395 pthread_key_create(&taskThreadKey
, NULL
);
1396 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1398 secdebug("serverxpc", "start");
1399 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1401 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1405 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1406 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1407 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1408 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1409 xpc_retain(connection
);
1411 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1412 securityd_xpc_dictionary_handler(connection
, event
);
1414 xpc_release(connection
);
1418 xpc_connection_resume(connection
);
1421 xpc_connection_resume(listener
);
1425 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1427 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1428 static void securityd_soscc_lock_hack() {
1429 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1431 __block MKBAssertionRef lockAssertion
= NULL
;
1434 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1435 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1436 // this code will need to be generalized / migrated away from just this specific purpose.
1437 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1438 char *event_description
= xpc_copy_description(object
);
1439 secnotice("events", "%s", event_description
);
1440 free(event_description
);
1443 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1444 rc
= notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1445 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: already holding lock %d", (int) (lockAssertion
!= NULL
));
1447 // Release previously held assertion (if present)
1448 CFReleaseSafe(lockAssertion
);
1450 // New lock assertion
1452 CFNumberRef cfn300
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &k300
);
1453 const void *keys
[] = {kMKBAssertionTypeKey
, kMKBAssertionTimeoutKey
};
1454 const void *vals
[] = {kMKBAssertionTypeProfile
, cfn300
};
1455 CFDictionaryRef lockOptions
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, vals
, 2,
1456 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1457 CFErrorRef err
= NULL
;
1459 lockAssertion
= MKBDeviceLockAssertion(lockOptions
, &err
);
1460 if (lockAssertion
) {
1461 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1462 xpc_transaction_begin();
1464 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, k300
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1465 xpc_transaction_end();
1468 secerror("Failed to take device lock assertion: %@", err
);
1471 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1473 CFReleaseSafe(cfn300
);
1474 CFReleaseSafe(lockOptions
);
1477 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1479 int main(int argc
, char *argv
[])
1481 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1482 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1483 seccritical("SIGSTOPing self, awaiting debugger");
1484 kill(getpid(), SIGSTOP
);
1485 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
1486 "Again, for good luck (or bad debuggers)");
1487 kill(getpid(), SIGSTOP
);
1490 const char *serviceName
= kSecuritydXPCServiceName
;
1492 serviceName
= kTrustdXPCServiceName
;
1493 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
1494 serviceName
= kTrustdAgentXPCServiceName
;
1497 securityd_init_server();
1498 securityd_xpc_init(serviceName
);
1500 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1501 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1502 securityd_soscc_lock_hack();
1503 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1510 /* vi:set ts=4 sw=4 et: */