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>
54 #include <AssertMacros.h>
55 #include <CoreFoundation/CFXPCBridge.h>
56 #include <CoreFoundation/CoreFoundation.h>
57 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
58 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
59 #include <MobileKeyBag/MobileKeyBag.h>
60 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
62 #include <bsm/libbsm.h>
63 #include <ipc/securityd_client.h>
64 #include <libkern/OSAtomic.h>
65 #include <mach/mach.h>
66 #include <mach/message.h>
69 #include <sys/queue.h>
70 #include <sys/sysctl.h>
72 #include <xpc/private.h>
75 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
76 #include <Security/SecTaskPriv.h>
79 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
80 CFStringRef entitlement
)
82 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
84 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
92 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
93 CFStringRef entitlement
)
95 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
98 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
99 CFIndex ix
, count
= CFArrayGetCount(value
);
100 for (ix
= 0; ix
< count
; ++ix
) {
101 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
102 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
117 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
118 return SecTaskCopyStringForEntitlement(task
,
119 kSecEntitlementApplicationIdentifier
);
122 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
123 return SecTaskCopyArrayOfStringsForEntitlement(task
,
124 kSecEntitlementAssociatedDomains
);
127 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
128 CFMutableArrayRef groups
= NULL
;
129 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
130 kSecEntitlementKeychainAccessGroups
);
131 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
132 kSecEntitlementAppleSecurityApplicationGroups
);
133 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
134 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
135 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
136 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
137 if ((appID
|| asagLen
) && !SecTaskEntitlementsValidated(task
)) {
138 CFReleaseNull(appID
);
142 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
144 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
);
146 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
148 CFArrayAppendValue(groups
, appID
);
150 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
151 #if TARGET_IPHONE_SIMULATOR
153 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
154 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
158 CFReleaseSafe(appID
);
159 CFReleaseSafe(keychainAccessGroups
);
160 CFReleaseSafe(appleSecurityApplicationGroups
);
164 static pthread_key_t taskThreadKey
;
165 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
166 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
167 if (taskRef
== NULL
) {
168 secerror("MISSING keychain entitlements: no stored taskRef found");
172 CFErrorRef error
= NULL
;
173 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
174 kSecEntitlementApplicationIdentifier
,
175 kSecEntitlementKeychainAccessGroups
,
176 kSecEntitlementAppleSecurityApplicationGroups
,
178 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
179 CFRelease(entitlementNames
);
181 if (rawEntitlements
== NULL
) {
182 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
183 CFReleaseSafe(error
);
184 __security_simulatecrash(CFSTR("failed to read keychain client entitlement(s)"), __sec_exception_code_MissingEntitlements
);
188 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
189 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
190 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
191 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
193 __security_simulatecrash(CFSTR("keychain entitlement(s) missing"), __sec_exception_code_MissingEntitlements
);
195 CFReleaseSafe(newAccessGroups
);
196 CFReleaseSafe(rawEntitlements
);
199 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
200 CFStringRef entitlement
) {
201 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
205 CFTypeID canModifyType
= CFGetTypeID(canModify
);
206 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
207 CFRelease(canModify
);
211 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
212 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
214 if (label_utf8
) { // Anything we would do here requires a user label
215 size_t password_length
= 0;
216 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
218 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
219 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
221 action(user_label
, user_password
);
223 CFReleaseNull(user_password
);
224 CFReleaseNull(user_label
);
228 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
229 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
231 if (label_utf8
) { // Anything we would do here requires a user label
232 size_t password_length
= 0;
233 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
234 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
236 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
237 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
238 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
240 action(user_label
, user_password
, dsid
);
243 CFReleaseNull(user_password
);
244 CFReleaseNull(user_label
);
248 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
249 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
250 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
251 secnotice("views", "Action Code Raw is %d", (int) number
);
252 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
254 action(user_label
, number
);
255 CFReleaseNull(user_label
);
258 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
261 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
265 xpc_dictionary_set_value(message
, key
, xpc_chain
);
266 xpc_release(xpc_chain
);
270 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
272 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
274 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
277 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
279 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
284 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
285 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
286 if (!xpc_certificates
)
287 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
288 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
289 return *certificates
;
292 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
293 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
294 if (!xpc_certificates
) {
295 *certificates
= NULL
;
298 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
299 return *certificates
;
302 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
303 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
309 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
310 return *policies
!= NULL
;
313 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
314 SecTrustStoreRef ts
= NULL
;
315 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
317 ts
= SecTrustStoreForDomainName(domain
, error
);
323 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
324 *pvalue
= xpc_dictionary_get_double(message
, key
);
325 if (*pvalue
== NAN
) {
326 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
331 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
332 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
335 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
336 CFDataRef data
= NULL
;
338 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
340 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
343 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
348 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
349 CFMutableArrayRef data_array
= NULL
;
350 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
351 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
352 size_t count
= xpc_array_get_count(xpc_data_array
);
353 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
354 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
357 for (ix
= 0; ix
< count
; ++ix
) {
358 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
360 CFRelease(data_array
);
363 CFArraySetValueAtIndex(data_array
, ix
, data
);
371 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
372 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
373 if (!xpc_data_array
) {
378 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
379 return *data_array
!= NULL
;
382 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
383 CFErrorRef error
= NULL
;
384 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
385 CFSetRef retval
= NULL
;
386 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
387 CFReleaseNull(error
);
392 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
394 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
395 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
396 xpc_release(xpc_array
);
398 CFReleaseNull(cf_array
);
402 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
405 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
407 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
408 xpc_release(xpc_array
);
413 CFReleaseNull(cf_array
);
418 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
419 xpc_type_t type
= xpc_get_type(event
);
420 __block CFErrorRef error
= NULL
;
421 xpc_object_t xpcError
= NULL
;
422 xpc_object_t replyMessage
= NULL
;
423 SecTaskRef clientTask
= NULL
;
424 CFDataRef clientAuditToken
= NULL
;
425 CFArrayRef accessGroups
= NULL
;
426 CFArrayRef domains
= NULL
;
428 secdebug("serverxpc", "entering");
429 if (type
== XPC_TYPE_DICTIONARY
) {
430 // TODO: Find out what we're dispatching.
431 replyMessage
= xpc_dictionary_create_reply(event
);
433 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
436 audit_token_t auditToken
= {};
437 xpc_connection_get_audit_token(connection
, &auditToken
);
439 clientTask
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
440 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
441 pthread_setspecific(taskThreadKey
, clientTask
);
442 accessGroups
= SecTaskCopyAccessGroups(clientTask
);
443 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
444 domains
= SecTaskCopySharedWebCredentialDomains(clientTask
);
447 // TODO: change back to secdebug
448 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
451 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
452 // Refer to rdar://problem/18615626&18616300 for more details.
453 int64_t minimumDirtyInterval
= (int64_t) (2 * NSEC_PER_SEC
);
454 xpc_transaction_begin();
455 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, minimumDirtyInterval
), dispatch_get_main_queue(), ^{
456 xpc_transaction_end();
460 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
461 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
462 (clientTask
&& SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementKeychainCloudCircle
));
464 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
465 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
467 if (!hasEntitlement
) {
468 CFErrorRef entitlementError
= NULL
;
469 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementKeychainCloudCircle
);
470 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
471 CFReleaseSafe(entitlementError
);
477 case sec_item_add_id
:
479 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
481 CFTypeRef result
= NULL
;
482 if (_SecItemAdd(query
, accessGroups
, &result
, &error
) && result
) {
483 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
490 case sec_item_copy_matching_id
:
492 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
494 CFTypeRef result
= NULL
;
495 if (_SecItemCopyMatching(query
, accessGroups
, &result
, &error
) && result
) {
496 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
503 case sec_item_update_id
:
505 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
507 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
508 if (attributesToUpdate
) {
509 bool result
= _SecItemUpdate(query
, attributesToUpdate
, accessGroups
, &error
);
510 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
511 CFRelease(attributesToUpdate
);
517 case sec_item_delete_id
:
519 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
521 bool result
= _SecItemDelete(query
, accessGroups
, &error
);
522 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
527 case sec_trust_store_contains_id
:
529 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
531 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
534 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
535 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
541 case sec_trust_store_set_trust_settings_id
:
543 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementModifyAnchorCertificates
)) {
544 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
546 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
548 CFTypeRef trustSettingsDictOrArray
= NULL
;
549 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
550 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
551 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
552 CFReleaseSafe(trustSettingsDictOrArray
);
554 CFRelease(certificate
);
558 SecError(errSecMissingEntitlement
, &error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementModifyAnchorCertificates
);
562 case sec_trust_store_remove_certificate_id
:
564 if (SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementModifyAnchorCertificates
)) {
565 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
567 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
569 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
570 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
575 SecError(errSecMissingEntitlement
, &error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementModifyAnchorCertificates
);
579 case sec_delete_all_id
:
580 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
582 case sec_trust_evaluate_id
:
584 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
585 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
587 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
588 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
589 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
590 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
591 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
592 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
593 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
594 // If we have no error yet, capture connection and reply in block and properly retain them.
595 xpc_retain(connection
);
596 CFRetainSafe(clientTask
);
597 CFRetainSafe(clientAuditToken
);
599 // Clear replyMessage so we don't send a synchronous reply.
600 xpc_object_t asyncReply
= replyMessage
;
603 SecTrustServerEvaluateBlock(clientAuditToken
,
604 certificates
, anchors
, anchorsOnly
, policies
, responses
, scts
, trustedLogs
, verifyTime
, accessGroups
,
605 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
606 // Send back reply now
608 CFRetain(replyError
);
610 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
611 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
612 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
613 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
616 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
617 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
619 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
620 xpc_release(xpcReplyError
);
622 CFRelease(replyError
);
624 secdebug("ipc", "%@ %@ reponding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
627 xpc_connection_send_message(connection
, asyncReply
);
628 xpc_release(asyncReply
);
629 xpc_release(connection
);
630 CFReleaseSafe(clientTask
);
631 CFReleaseSafe(clientAuditToken
);
634 CFReleaseSafe(policies
);
635 CFReleaseSafe(anchors
);
636 CFReleaseSafe(certificates
);
637 CFReleaseSafe(responses
);
639 CFReleaseSafe(trustedLogs
);
642 case sec_keychain_backup_id
:
644 CFDataRef keybag
= NULL
, passcode
= NULL
;
645 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
646 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
647 CFDataRef backup
= _SecServerKeychainBackup(keybag
, passcode
, &error
);
649 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
652 CFReleaseSafe(passcode
);
654 CFReleaseSafe(keybag
);
658 case sec_keychain_restore_id
:
660 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
662 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
664 CFDataRef passcode
= NULL
;
665 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
666 bool result
= _SecServerKeychainRestore(backup
, keybag
, passcode
, &error
);
667 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
668 CFReleaseSafe(passcode
);
676 case sec_keychain_sync_update_message_id
:
678 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
680 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
681 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
682 CFReleaseNull(result
);
684 CFReleaseNull(updates
);
687 case sec_keychain_backup_syncable_id
:
689 CFDictionaryRef oldbackup
= NULL
;
690 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
691 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
693 CFDataRef passcode
= NULL
;
694 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
695 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
697 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
698 CFRelease(newbackup
);
700 CFReleaseSafe(passcode
);
704 CFReleaseSafe(oldbackup
);
708 case sec_keychain_restore_syncable_id
:
710 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
712 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
714 CFDataRef passcode
= NULL
;
715 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
716 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
717 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
718 CFReleaseSafe(passcode
);
726 case sec_item_backup_copy_names_id
:
728 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
729 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
730 CFReleaseSafe(names
);
733 case sec_item_backup_handoff_fd_id
:
735 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
738 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
739 CFRelease(backupName
);
741 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
746 case sec_item_backup_set_confirmed_manifest_id
:
748 CFDataRef keybagDigest
= NULL
;
749 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
750 CFDataRef manifest
= NULL
;
751 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
752 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
754 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
755 CFRelease(backupName
);
756 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
758 CFReleaseSafe(manifest
);
760 CFRelease(keybagDigest
);
764 case sec_item_backup_restore_id
:
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
);
791 case sec_ota_pki_asset_version_id
:
793 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
794 SecOTAPKIGetCurrentAssetVersion(&error
));
797 case sec_add_shared_web_credential_id
:
799 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
801 CFTypeRef result
= NULL
;
802 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
803 if (_SecAddSharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
804 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
807 CFReleaseSafe(appID
);
812 case sec_copy_shared_web_credential_id
:
814 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
816 CFTypeRef result
= NULL
;
817 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
818 if (_SecCopySharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
819 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
822 CFReleaseSafe(appID
);
827 case sec_get_log_settings_id
:
829 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
831 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
833 CFReleaseSafe(currentList
);
836 case sec_set_xpc_log_settings_id
:
838 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
840 SecSetXPCLogSettings_Server(newSettings
, &error
);
842 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
843 CFReleaseNull(newSettings
);
846 case sec_set_circle_log_settings_id
:
848 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
850 SecSetCircleLogSettings_Server(newSettings
, &error
);
852 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
853 CFReleaseNull(newSettings
);
856 case sec_otr_session_create_remote_id
:
858 CFDataRef publicPeerId
= NULL
;
859 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
860 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
862 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
863 CFRelease(otrSession
);
865 CFReleaseSafe(publicPeerId
);
869 case sec_otr_session_process_packet_remote_id
:
871 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
872 bool readyForMessages
= false;
873 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
874 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
875 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
877 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
878 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
879 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
880 CFRelease(outputSessionData
);
881 CFRelease(outputPacket
);
883 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
885 CFReleaseSafe(inputPacket
);
887 CFReleaseSafe(sessionData
);
891 case kSecXPCOpTryUserCredentials
:
892 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
893 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
894 SOSCCTryUserCredentials_Server(label
, password
, &error
));
897 case kSecXPCOpSetUserCredentials
:
898 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
899 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
900 SOSCCSetUserCredentials_Server(label
, password
, &error
));
903 case kSecXPCOpSetUserCredentialsAndDSID
:
904 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
905 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
906 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
910 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
911 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
912 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
915 case kSecXPCOpViewSet
:
917 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
918 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
919 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
920 CFReleaseNull(enabledViews
);
921 CFReleaseNull(disabledViews
);
924 case kSecXPCOpSecurityProperty
:
925 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
926 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
927 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
930 case kSecXPCOpCanAuthenticate
:
931 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
932 SOSCCCanAuthenticate_Server(&error
));
934 case kSecXPCOpPurgeUserCredentials
:
935 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
936 SOSCCPurgeUserCredentials_Server(&error
));
938 case kSecXPCOpDeviceInCircle
:
939 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
940 SOSCCThisDeviceIsInCircle_Server(&error
));
942 case kSecXPCOpRequestToJoin
:
943 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
944 SOSCCRequestToJoinCircle_Server(&error
));
946 case kSecXPCOpRequestToJoinAfterRestore
:
947 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
948 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
950 case kSecXPCOpRequestEnsureFreshParameters
:
951 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
952 SOSCCRequestEnsureFreshParameters_Server(&error
));
954 case kSecXPCOpGetAllTheRings
:
956 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
957 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
958 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
959 xpc_release(xpc_dictionary
);
962 case kSecXPCOpApplyToARing
:
964 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
965 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
966 CFReleaseNull(ringName
);
969 case kSecXPCOpWithdrawlFromARing
:
971 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
972 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
973 CFReleaseNull(ringName
);
976 case kSecXPCOpRingStatus
:
978 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
979 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
980 CFReleaseNull(ringName
);
983 case kSecXPCOpEnableRing
:
985 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
986 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
987 CFReleaseNull(ringName
);
990 case kSecXPCOpRequestDeviceID
:
992 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
994 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
996 CFReleaseNull(deviceID
);
999 case kSecXPCOpSetDeviceID
:
1001 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1002 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1006 case kSecXPCOpHandleIDSMessage
:
1008 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1009 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1014 case kSecXPCOpSendIDSMessage
:
1016 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1017 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1018 CFReleaseNull(message
);
1021 case kSecXPCOpPingTest
:
1023 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1024 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1025 CFReleaseNull(message
);
1028 case kSecXPCOpIDSDeviceID
:
1030 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1033 case kSecXPCOpAccountSetToNew
:
1034 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1036 case kSecXPCOpResetToOffering
:
1037 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1038 SOSCCResetToOffering_Server(&error
));
1040 case kSecXPCOpResetToEmpty
:
1041 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1042 SOSCCResetToEmpty_Server(&error
));
1044 case kSecXPCOpRemoveThisDeviceFromCircle
:
1045 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1046 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1048 case kSecXPCOpRemovePeersFromCircle
:
1050 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfos
, &error
);
1051 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1052 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1053 CFReleaseNull(applicants
);
1056 case kSecXPCOpLoggedOutOfAccount
:
1057 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1058 SOSCCLoggedOutOfAccount_Server(&error
));
1060 case kSecXPCOpBailFromCircle
:
1062 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1063 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1064 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1067 case kSecXPCOpAcceptApplicants
:
1069 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1070 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1071 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1072 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1073 CFReleaseSafe(applicants
);
1076 case kSecXPCOpRejectApplicants
:
1078 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1079 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1080 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1081 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1082 CFReleaseSafe(applicants
);
1085 case kSecXPCOpSetNewPublicBackupKey
:
1087 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1088 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1089 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1090 CFReleaseNull(peerInfo
);
1092 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1093 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1094 xpc_release(xpc_object
);
1096 CFReleaseNull(peerInfoData
);
1097 CFReleaseSafe(publicBackupKey
);
1101 case kSecXPCOpSetBagForAllSlices
:
1103 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1104 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1105 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1106 CFReleaseSafe(backupSlice
);
1109 case kSecXPCOpCopyApplicantPeerInfo
:
1110 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1111 SOSCCCopyApplicantPeerInfo_Server(&error
),
1114 case kSecXPCOpCopyValidPeerPeerInfo
:
1115 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1116 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1119 case kSecXPCOpValidateUserPublic
:
1121 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1122 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1125 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1126 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1127 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1130 case kSecXPCOpCopyGenerationPeerInfo
:
1131 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1132 SOSCCCopyGenerationPeerInfo_Server(&error
));
1134 case kSecXPCOpCopyRetirementPeerInfo
:
1135 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1136 SOSCCCopyRetirementPeerInfo_Server(&error
),
1139 case kSecXPCOpCopyViewUnawarePeerInfo
:
1140 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1141 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1144 case kSecXPCOpCopyEngineState
:
1146 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1148 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1149 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1150 xpc_release(xpc_array
);
1152 CFReleaseNull(array
);
1155 case kSecXPCOpCopyPeerPeerInfo
:
1156 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1157 SOSCCCopyPeerPeerInfo_Server(&error
),
1160 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1161 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1162 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1165 case kSecXPCOpCopyMyPeerInfo
:
1167 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1168 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1169 CFReleaseNull(peerInfo
);
1171 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1172 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1173 xpc_release(xpc_object
);
1175 CFReleaseNull(peerInfoData
);
1178 case kSecXPCOpGetLastDepartureReason
:
1179 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1180 SOSCCGetLastDepartureReason_Server(&error
));
1182 case kSecXPCOpSetLastDepartureReason
:
1184 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1185 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1186 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1189 case kSecXPCOpProcessSyncWithAllPeers
:
1190 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1191 SOSCCProcessSyncWithAllPeers_Server(&error
));
1193 case soscc_EnsurePeerRegistration_id
:
1194 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1195 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1197 case kSecXPCOpCopyIncompatibilityInfo
:
1199 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1200 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1204 case kSecXPCOpOTAGetEscrowCertificates
:
1206 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1207 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1209 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1210 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1211 xpc_release(xpc_array
);
1213 CFReleaseNull(array
);
1216 case kSecXPCOpOTAPKIGetNewAsset
:
1217 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1218 SecOTAPKISignalNewAsset(&error
));
1220 case kSecXPCOpRollKeys
:
1222 bool force
= xpc_dictionary_get_bool(event
, "force");
1223 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1224 _SecServerRollKeys(force
, &error
));
1227 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1229 CFDataRef cfbytes
= NULL
;
1230 const uint8_t *bytes
= NULL
;
1233 bytes
= xpc_dictionary_get_data(event
,
1234 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1236 SOSCreateError(kSOSErrorBadKey
,
1237 CFSTR("missing autoaccept info"), NULL
, &error
);
1241 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1243 SOSCreateError(kSOSErrorAllocationFailure
,
1244 CFSTR("could not allocate autoaccept info"),
1249 xpc_dictionary_set_bool(replyMessage
,
1251 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1255 case kSecXPCOpWaitForInitialSync
:
1256 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1257 SOSCCWaitForInitialSync_Server(&error
));
1260 case kSecXPCOpCopyYetToSyncViews
:
1262 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1264 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1265 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1266 xpc_release(xpc_array
);
1268 CFReleaseNull(array
);
1271 case kSecXPCOpSetEscrowRecord
:
1273 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1274 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1276 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1278 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1280 CFReleaseNull(escrow_label
);
1283 case kSecXPCOpGetEscrowRecord
:
1285 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1287 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1288 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1289 xpc_release(xpc_dictionary
);
1291 CFReleaseNull(record
);
1294 case kSecXPCOpCheckPeerAvailability
:
1296 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1307 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1308 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1309 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1310 secwarning("Authentication is needed %@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1312 secerror("%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1314 xpcError
= SecCreateXPCObjectWithCFError(error
);
1316 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1318 } else if (replyMessage
) {
1319 secdebug("ipc", "%@ %@ responding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1322 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1323 secerror("%@: returning error: %@", clientTask
, error
);
1324 xpcError
= SecCreateXPCObjectWithCFError(error
);
1325 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1329 xpc_connection_send_message(connection
, replyMessage
);
1330 xpc_release(replyMessage
);
1333 xpc_release(xpcError
);
1334 CFReleaseSafe(error
);
1335 CFReleaseSafe(accessGroups
);
1336 CFReleaseSafe(domains
);
1337 pthread_setspecific(taskThreadKey
, NULL
);
1338 CFReleaseSafe(clientTask
);
1339 CFReleaseSafe(clientAuditToken
);
1342 static void securityd_xpc_init(const char *service_name
)
1344 pthread_key_create(&taskThreadKey
, NULL
);
1345 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1347 secdebug("serverxpc", "start");
1348 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1350 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1354 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1355 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1356 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1357 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1358 xpc_retain(connection
);
1360 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1361 securityd_xpc_dictionary_handler(connection
, event
);
1363 xpc_release(connection
);
1367 xpc_connection_resume(connection
);
1370 xpc_connection_resume(listener
);
1374 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1376 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1377 static void securityd_soscc_lock_hack() {
1378 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1380 __block MKBAssertionRef lockAssertion
= NULL
;
1383 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1384 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1385 // this code will need to be generalized / migrated away from just this specific purpose.
1386 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1387 char *event_description
= xpc_copy_description(object
);
1388 secnotice("events", "%s", event_description
);
1389 free(event_description
);
1392 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1393 rc
= notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1394 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: already holding lock %d", (int) (lockAssertion
!= NULL
));
1396 // Release previously held assertion (if present)
1397 CFReleaseSafe(lockAssertion
);
1399 // New lock assertion
1401 CFNumberRef cfn300
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &k300
);
1402 const void *keys
[] = {kMKBAssertionTypeKey
, kMKBAssertionTimeoutKey
};
1403 const void *vals
[] = {kMKBAssertionTypeProfile
, cfn300
};
1404 CFDictionaryRef lockOptions
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, vals
, 2,
1405 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1406 CFErrorRef err
= NULL
;
1408 lockAssertion
= MKBDeviceLockAssertion(lockOptions
, &err
);
1409 if (lockAssertion
) {
1410 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1411 xpc_transaction_begin();
1413 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, k300
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1414 xpc_transaction_end();
1417 secerror("Failed to take device lock assertion: %@", err
);
1420 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1422 CFReleaseSafe(cfn300
);
1423 CFReleaseSafe(lockOptions
);
1426 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1428 int main(int argc
, char *argv
[])
1430 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1431 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1432 seccritical("SIGSTOPing self, awaiting debugger");
1433 kill(getpid(), SIGSTOP
);
1434 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
1435 "Again, for good luck (or bad debuggers)");
1436 kill(getpid(), SIGSTOP
);
1439 const char *serviceName
= kSecuritydXPCServiceName
;
1441 serviceName
= kTrustdXPCServiceName
;
1442 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
1443 serviceName
= kTrustdAgentXPCServiceName
;
1446 securityd_init_server();
1447 securityd_xpc_init(serviceName
);
1449 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1450 #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1451 securityd_soscc_lock_hack();
1452 #endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
1459 /* vi:set ts=4 sw=4 et: */