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_EMBEDDED
60 #include <MobileKeyBag/MobileKeyBag.h>
63 #include <Security/SecTaskPriv.h>
66 #include <bsm/libbsm.h>
67 #include <ipc/securityd_client.h>
68 #include <libkern/OSAtomic.h>
69 #include <mach/mach.h>
70 #include <mach/message.h>
73 #include <sys/queue.h>
74 #include <sys/sysctl.h>
76 #include <xpc/private.h>
80 static int inMultiUser
= -1;
84 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
85 CFStringRef entitlement
)
87 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
89 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
97 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
98 CFStringRef entitlement
)
100 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
103 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
104 CFIndex ix
, count
= CFArrayGetCount(value
);
105 for (ix
= 0; ix
< count
; ++ix
) {
106 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
107 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
122 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
123 return SecTaskCopyStringForEntitlement(task
,
124 kSecEntitlementApplicationIdentifier
);
127 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
128 return SecTaskCopyArrayOfStringsForEntitlement(task
,
129 kSecEntitlementAssociatedDomains
);
132 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
133 CFMutableArrayRef groups
= NULL
;
134 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
135 kSecEntitlementKeychainAccessGroups
);
136 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
137 kSecEntitlementAppleSecurityApplicationGroups
);
138 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
139 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
140 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
141 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
142 if ((appID
|| asagLen
) && !SecTaskEntitlementsValidated(task
)) {
143 CFReleaseNull(appID
);
147 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
149 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
);
151 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
153 CFArrayAppendValue(groups
, appID
);
155 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
156 #if TARGET_IPHONE_SIMULATOR
158 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
159 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
163 CFReleaseSafe(appID
);
164 CFReleaseSafe(keychainAccessGroups
);
165 CFReleaseSafe(appleSecurityApplicationGroups
);
169 static pthread_key_t taskThreadKey
;
170 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
171 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
172 if (taskRef
== NULL
) {
173 secerror("MISSING keychain entitlements: no stored taskRef found");
177 CFErrorRef error
= NULL
;
178 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
179 kSecEntitlementApplicationIdentifier
,
180 kSecEntitlementKeychainAccessGroups
,
181 kSecEntitlementAppleSecurityApplicationGroups
,
183 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
184 CFRelease(entitlementNames
);
186 if (rawEntitlements
== NULL
) {
187 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
188 CFReleaseSafe(error
);
189 __security_simulatecrash(CFSTR("failed to read keychain client entitlement(s)"), __sec_exception_code_MissingEntitlements
);
193 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
194 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
195 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
196 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
198 __security_simulatecrash(CFSTR("keychain entitlement(s) missing"), __sec_exception_code_MissingEntitlements
);
200 CFReleaseSafe(newAccessGroups
);
201 CFReleaseSafe(rawEntitlements
);
204 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
205 CFStringRef entitlement
) {
206 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
210 CFTypeID canModifyType
= CFGetTypeID(canModify
);
211 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
212 CFRelease(canModify
);
216 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
217 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
219 if (label_utf8
) { // Anything we would do here requires a user label
220 size_t password_length
= 0;
221 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
223 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
224 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
226 action(user_label
, user_password
);
228 CFReleaseNull(user_password
);
229 CFReleaseNull(user_label
);
233 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
234 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
236 if (label_utf8
) { // Anything we would do here requires a user label
237 size_t password_length
= 0;
238 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
239 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
241 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
242 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
243 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
245 action(user_label
, user_password
, dsid
);
248 CFReleaseNull(user_password
);
249 CFReleaseNull(user_label
);
253 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
254 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
255 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
256 secnotice("views", "Action Code Raw is %d", (int) number
);
257 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
259 action(user_label
, number
);
260 CFReleaseNull(user_label
);
263 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
266 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
270 xpc_dictionary_set_value(message
, key
, xpc_chain
);
271 xpc_release(xpc_chain
);
275 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
277 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
279 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
282 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
284 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
289 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
290 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
291 if (!xpc_certificates
)
292 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
293 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
294 return *certificates
;
297 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
298 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
299 if (!xpc_certificates
) {
300 *certificates
= NULL
;
303 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
304 return *certificates
;
307 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
308 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
314 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
315 return *policies
!= NULL
;
318 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
319 SecTrustStoreRef ts
= NULL
;
320 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
322 ts
= SecTrustStoreForDomainName(domain
, error
);
328 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
329 *pvalue
= xpc_dictionary_get_double(message
, key
);
330 if (*pvalue
== NAN
) {
331 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
336 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
337 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
340 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
341 CFDataRef data
= NULL
;
343 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
345 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
348 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
353 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
354 CFMutableArrayRef data_array
= NULL
;
355 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
356 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
357 size_t count
= xpc_array_get_count(xpc_data_array
);
358 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
359 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
362 for (ix
= 0; ix
< count
; ++ix
) {
363 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
365 CFRelease(data_array
);
368 CFArraySetValueAtIndex(data_array
, ix
, data
);
376 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
377 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
378 if (!xpc_data_array
) {
383 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
384 return *data_array
!= NULL
;
387 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
388 CFErrorRef error
= NULL
;
389 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
390 CFSetRef retval
= NULL
;
391 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
392 CFReleaseNull(error
);
397 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
399 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
400 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
401 xpc_release(xpc_array
);
403 CFReleaseNull(cf_array
);
407 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
410 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
412 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
413 xpc_release(xpc_array
);
418 CFReleaseNull(cf_array
);
423 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
426 if (fstat(fd
, &sb
) < 0) {
430 *size
= (size_t)sb
.st_size
;
431 if ((off_t
)*size
!= sb
.st_size
) {
435 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
436 if (*mem
== MAP_FAILED
) {
440 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
444 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
446 CFIndex count
= CFDataGetLength(data
);
447 const uint8_t *ptr
= CFDataGetBytePtr(data
);
448 bool writeResult
= false;
451 ssize_t ret
= write(fd
, ptr
, count
);
466 EntitlementMissing(enum SecXPCOperation op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
468 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription(op
), clientTask
, entitlement
);
473 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
474 xpc_type_t type
= xpc_get_type(event
);
475 __block CFErrorRef error
= NULL
;
476 xpc_object_t xpcError
= NULL
;
477 xpc_object_t replyMessage
= NULL
;
478 CFDataRef clientAuditToken
= NULL
;
479 CFArrayRef domains
= NULL
;
480 SecurityClient client
= {
482 .accessGroups
= NULL
,
484 .uid
= xpc_connection_get_euid(connection
),
485 .allowSystemKeychain
= false,
486 .allowSyncBubbleKeychain
= false,
487 .isNetworkExtension
= false,
489 .inMultiUser
= inMultiUser
,
493 secdebug("serverxpc", "entering");
494 if (type
== XPC_TYPE_DICTIONARY
) {
495 // TODO: Find out what we're dispatching.
496 replyMessage
= xpc_dictionary_create_reply(event
);
498 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
500 assert(inMultiUser
!= -1);
502 client
.activeUser
= MKBForegroundUserSessionID(&error
);
503 if (client
.activeUser
== -1 || client
.activeUser
== 0) {
505 client
.activeUser
= 0;
509 * If we are a edu mode user, and its not the active user,
510 * then the request is coming from inside the syncbubble.
512 * otherwise we are going to execute the request as the
516 if (client
.uid
> 501 && (uid_t
)client
.activeUser
!= client
.uid
) {
517 secinfo("serverxpc", "securityd client: sync bubble user");
518 client
.musr
= SecMUSRCreateSyncBubbleUserUUID(client
.uid
);
519 client
.keybag
= KEYBAG_DEVICE
;
521 secinfo("serverxpc", "securityd client: active user");
522 client
.musr
= SecMUSRCreateActiveUserUUID(client
.activeUser
);
523 client
.uid
= (uid_t
)client
.activeUser
;
524 client
.keybag
= KEYBAG_DEVICE
;
529 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
532 audit_token_t auditToken
= {};
533 xpc_connection_get_audit_token(connection
, &auditToken
);
535 client
.task
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
536 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
537 pthread_setspecific(taskThreadKey
, client
.task
);
538 client
.accessGroups
= SecTaskCopyAccessGroups(client
.task
);
539 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
540 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
543 client
.allowSystemKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateSystemKeychain
);
544 client
.isNetworkExtension
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateNetworkExtension
);
546 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
547 if (client
.inMultiUser
) {
548 client
.allowSyncBubbleKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
);
552 // TODO: change back to secdebug
553 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
556 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
557 // Refer to rdar://problem/18615626&18616300 for more details.
558 int64_t minimumDirtyInterval
= (int64_t) (2 * NSEC_PER_SEC
);
559 xpc_transaction_begin();
560 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, minimumDirtyInterval
), dispatch_get_main_queue(), ^{
561 xpc_transaction_end();
565 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
566 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
567 (client
.task
&& SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
));
569 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
570 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
572 if (!hasEntitlement
) {
573 CFErrorRef entitlementError
= NULL
;
574 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
);
575 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
576 CFReleaseSafe(entitlementError
);
582 case sec_item_add_id
:
584 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
586 CFTypeRef result
= NULL
;
587 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
588 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
595 case sec_item_copy_matching_id
:
597 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
599 CFTypeRef result
= NULL
;
600 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
601 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
608 case sec_item_update_id
:
610 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
612 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
613 if (attributesToUpdate
) {
614 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
615 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
616 CFRelease(attributesToUpdate
);
622 case sec_item_delete_id
:
624 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
626 bool result
= _SecItemDelete(query
, &client
, &error
);
627 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
632 case sec_trust_store_contains_id
:
634 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
636 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
639 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
640 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
646 case sec_trust_store_set_trust_settings_id
:
648 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementModifyAnchorCertificates
)) {
649 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
651 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
653 CFTypeRef trustSettingsDictOrArray
= NULL
;
654 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
655 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
656 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
657 CFReleaseSafe(trustSettingsDictOrArray
);
659 CFRelease(certificate
);
663 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
);
667 case sec_trust_store_remove_certificate_id
:
669 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementModifyAnchorCertificates
)) {
670 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
672 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
674 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
675 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
680 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
);
684 case sec_delete_all_id
:
685 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
687 case sec_trust_evaluate_id
:
689 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
690 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
692 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
693 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
694 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
695 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
696 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
697 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
698 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
699 // If we have no error yet, capture connection and reply in block and properly retain them.
700 xpc_retain(connection
);
701 CFRetainSafe(client
.task
);
702 CFRetainSafe(clientAuditToken
);
704 // Clear replyMessage so we don't send a synchronous reply.
705 xpc_object_t asyncReply
= replyMessage
;
708 SecTrustServerEvaluateBlock(clientAuditToken
,
709 certificates
, anchors
, anchorsOnly
, policies
, responses
, scts
, trustedLogs
, verifyTime
, client
.accessGroups
,
710 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
711 // Send back reply now
713 CFRetain(replyError
);
715 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
716 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
717 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
718 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
721 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
722 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
724 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
725 xpc_release(xpcReplyError
);
727 CFRelease(replyError
);
729 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
732 xpc_connection_send_message(connection
, asyncReply
);
733 xpc_release(asyncReply
);
734 xpc_release(connection
);
735 CFReleaseSafe(client
.task
);
736 CFReleaseSafe(clientAuditToken
);
739 CFReleaseSafe(policies
);
740 CFReleaseSafe(anchors
);
741 CFReleaseSafe(certificates
);
742 CFReleaseSafe(responses
);
744 CFReleaseSafe(trustedLogs
);
747 case sec_keychain_backup_id
:
749 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
750 CFDataRef keybag
= NULL
, passcode
= NULL
;
751 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
752 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
753 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, &error
);
755 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
757 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
759 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
763 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
764 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
768 CFReleaseSafe(passcode
);
770 CFReleaseSafe(keybag
);
773 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
777 case sec_keychain_restore_id
:
779 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
780 CFDataRef backup
= NULL
;
784 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
786 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
788 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
791 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
793 CFDataRef passcode
= NULL
;
794 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
795 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
796 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
797 CFReleaseSafe(passcode
);
807 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
811 case sec_keychain_sync_update_message_id
:
813 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
815 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
816 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
817 CFReleaseNull(result
);
819 CFReleaseNull(updates
);
822 case sec_keychain_backup_syncable_id
:
824 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
826 CFDictionaryRef oldbackup
= NULL
;
827 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
828 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
830 CFDataRef passcode
= NULL
;
831 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
832 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
834 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
835 CFRelease(newbackup
);
837 CFReleaseSafe(passcode
);
841 CFReleaseSafe(oldbackup
);
844 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
848 case sec_keychain_restore_syncable_id
:
850 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
852 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
854 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
856 CFDataRef passcode
= NULL
;
857 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
858 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
859 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
860 CFReleaseSafe(passcode
);
867 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
871 case sec_item_backup_copy_names_id
:
873 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
874 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
875 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
876 CFReleaseSafe(names
);
878 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
882 case sec_item_backup_handoff_fd_id
:
884 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
885 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
888 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
889 CFRelease(backupName
);
891 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
895 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
899 case sec_item_backup_set_confirmed_manifest_id
:
901 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
902 CFDataRef keybagDigest
= NULL
;
903 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
904 CFDataRef manifest
= NULL
;
905 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
906 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
908 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
909 CFRelease(backupName
);
910 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
912 CFReleaseSafe(manifest
);
914 CFReleaseNull(keybagDigest
);
917 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
921 case sec_item_backup_restore_id
:
923 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
925 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
927 CFStringRef peerID
= NULL
;
928 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
929 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
931 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
933 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
935 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
942 CFReleaseSafe(peerID
);
944 CFRelease(backupName
);
946 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
948 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
952 case sec_ota_pki_asset_version_id
:
954 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
955 SecOTAPKIGetCurrentAssetVersion(&error
));
958 case sec_add_shared_web_credential_id
:
960 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
962 CFTypeRef result
= NULL
;
963 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
964 if (_SecAddSharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
965 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
968 CFReleaseSafe(appID
);
973 case sec_copy_shared_web_credential_id
:
975 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
977 CFTypeRef result
= NULL
;
978 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
979 if (_SecCopySharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
980 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
983 CFReleaseSafe(appID
);
988 case sec_get_log_settings_id
:
990 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
992 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
994 CFReleaseSafe(currentList
);
997 case sec_set_xpc_log_settings_id
:
999 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1001 SecSetXPCLogSettings_Server(newSettings
, &error
);
1003 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1004 CFReleaseNull(newSettings
);
1007 case sec_set_circle_log_settings_id
:
1009 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1011 SecSetCircleLogSettings_Server(newSettings
, &error
);
1013 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1014 CFReleaseNull(newSettings
);
1017 case sec_otr_session_create_remote_id
:
1019 CFDataRef publicPeerId
= NULL
;
1020 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
1021 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
1023 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
1024 CFRelease(otrSession
);
1026 CFReleaseSafe(publicPeerId
);
1030 case sec_otr_session_process_packet_remote_id
:
1032 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
1033 bool readyForMessages
= false;
1034 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
1035 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
1036 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
1038 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
1039 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
1040 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
1041 CFRelease(outputSessionData
);
1042 CFRelease(outputPacket
);
1044 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1046 CFReleaseSafe(inputPacket
);
1048 CFReleaseSafe(sessionData
);
1052 case kSecXPCOpTryUserCredentials
:
1053 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1054 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1055 SOSCCTryUserCredentials_Server(label
, password
, &error
));
1058 case kSecXPCOpSetUserCredentials
:
1059 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1060 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1061 SOSCCSetUserCredentials_Server(label
, password
, &error
));
1064 case kSecXPCOpSetUserCredentialsAndDSID
:
1065 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
1066 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1067 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
1071 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
1072 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1073 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
1076 case kSecXPCOpViewSet
:
1078 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
1079 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
1080 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
1081 CFReleaseNull(enabledViews
);
1082 CFReleaseNull(disabledViews
);
1085 case kSecXPCOpSecurityProperty
:
1086 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
1087 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1088 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
1091 case kSecXPCOpCanAuthenticate
:
1092 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1093 SOSCCCanAuthenticate_Server(&error
));
1095 case kSecXPCOpPurgeUserCredentials
:
1096 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1097 SOSCCPurgeUserCredentials_Server(&error
));
1099 case kSecXPCOpDeviceInCircle
:
1100 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1101 SOSCCThisDeviceIsInCircle_Server(&error
));
1103 case kSecXPCOpRequestToJoin
:
1104 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1105 SOSCCRequestToJoinCircle_Server(&error
));
1107 case kSecXPCOpRequestToJoinAfterRestore
:
1108 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1109 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
1111 case kSecXPCOpRequestEnsureFreshParameters
:
1112 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1113 SOSCCRequestEnsureFreshParameters_Server(&error
));
1115 case kSecXPCOpGetAllTheRings
:
1117 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
1118 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
1119 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1120 xpc_release(xpc_dictionary
);
1123 case kSecXPCOpApplyToARing
:
1125 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1126 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
1127 CFReleaseNull(ringName
);
1130 case kSecXPCOpWithdrawlFromARing
:
1132 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1133 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
1134 CFReleaseNull(ringName
);
1137 case kSecXPCOpRingStatus
:
1139 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1140 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
1141 CFReleaseNull(ringName
);
1144 case kSecXPCOpEnableRing
:
1146 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1147 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
1148 CFReleaseNull(ringName
);
1151 case kSecXPCOpRequestDeviceID
:
1153 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
1155 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
1157 CFReleaseNull(deviceID
);
1160 case kSecXPCOpSetDeviceID
:
1162 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1163 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1167 case kSecXPCOpHandleIDSMessage
:
1169 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1170 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1175 case kSecXPCOpSendIDSMessage
:
1177 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1178 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1179 CFReleaseNull(message
);
1182 case kSecXPCOpPingTest
:
1184 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1185 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1186 CFReleaseNull(message
);
1189 case kSecXPCOpIDSDeviceID
:
1191 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1194 case kSecXPCOpAccountSetToNew
:
1195 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1197 case kSecXPCOpResetToOffering
:
1198 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1199 SOSCCResetToOffering_Server(&error
));
1201 case kSecXPCOpResetToEmpty
:
1202 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1203 SOSCCResetToEmpty_Server(&error
));
1205 case kSecXPCOpRemoveThisDeviceFromCircle
:
1206 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1207 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1209 case kSecXPCOpRemovePeersFromCircle
:
1211 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfos
, &error
);
1212 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1213 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1214 CFReleaseNull(applicants
);
1217 case kSecXPCOpLoggedOutOfAccount
:
1218 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1219 SOSCCLoggedOutOfAccount_Server(&error
));
1221 case kSecXPCOpBailFromCircle
:
1223 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1224 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1225 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1228 case kSecXPCOpAcceptApplicants
:
1230 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1231 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1232 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1233 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1234 CFReleaseSafe(applicants
);
1237 case kSecXPCOpRejectApplicants
:
1239 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1240 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1241 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1242 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1243 CFReleaseSafe(applicants
);
1246 case kSecXPCOpSetNewPublicBackupKey
:
1248 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
1249 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1250 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1251 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1252 CFReleaseNull(peerInfo
);
1254 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1255 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1256 xpc_release(xpc_object
);
1258 CFReleaseNull(peerInfoData
);
1259 CFReleaseSafe(publicBackupKey
);
1262 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
1266 case kSecXPCOpSetBagForAllSlices
:
1268 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
1269 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1270 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1271 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1272 CFReleaseSafe(backupSlice
);
1274 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
1278 case kSecXPCOpCopyApplicantPeerInfo
:
1279 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1280 SOSCCCopyApplicantPeerInfo_Server(&error
),
1283 case kSecXPCOpCopyValidPeerPeerInfo
:
1284 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1285 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1288 case kSecXPCOpValidateUserPublic
:
1290 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1291 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1294 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1295 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1296 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1299 case kSecXPCOpCopyGenerationPeerInfo
:
1300 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1301 SOSCCCopyGenerationPeerInfo_Server(&error
));
1303 case kSecXPCOpCopyRetirementPeerInfo
:
1304 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1305 SOSCCCopyRetirementPeerInfo_Server(&error
),
1308 case kSecXPCOpCopyViewUnawarePeerInfo
:
1309 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1310 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1313 case kSecXPCOpCopyAccountData
:
1315 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1316 xpc_object_t xpc_account_object
= NULL
;
1317 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1319 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1321 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1322 CFReleaseNull(accountData
);
1325 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1329 case kSecXPCOpDeleteAccountData
:
1331 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1332 bool status
= SOSCCDeleteAccountState_Server(&error
);
1333 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1336 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1341 case kSecXPCOpCopyEngineData
:
1343 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1345 xpc_object_t xpc_engine_object
= NULL
;
1346 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1348 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1350 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1351 CFReleaseNull(engineData
);
1355 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1359 case kSecXPCOpDeleteEngineData
:
1361 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1363 bool status
= SOSCCDeleteEngineState_Server(&error
);
1364 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1367 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1371 case kSecXPCOpCopyEngineState
:
1373 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1375 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1377 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1378 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1379 xpc_release(xpc_array
);
1381 CFReleaseNull(array
);
1384 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1388 case kSecXPCOpCopyPeerPeerInfo
:
1389 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1390 SOSCCCopyPeerPeerInfo_Server(&error
),
1393 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1394 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1395 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1398 case kSecXPCOpCopyMyPeerInfo
:
1400 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1401 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1402 CFReleaseNull(peerInfo
);
1404 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1405 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1406 xpc_release(xpc_object
);
1408 CFReleaseNull(peerInfoData
);
1411 case kSecXPCOpGetLastDepartureReason
:
1412 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1413 SOSCCGetLastDepartureReason_Server(&error
));
1415 case kSecXPCOpSetLastDepartureReason
:
1417 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1418 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1419 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1422 case kSecXPCOpProcessSyncWithAllPeers
:
1423 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1424 SOSCCProcessSyncWithAllPeers_Server(&error
));
1426 case soscc_EnsurePeerRegistration_id
:
1427 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1428 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1430 case kSecXPCOpCopyIncompatibilityInfo
:
1432 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1433 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1437 case kSecXPCOpOTAGetEscrowCertificates
:
1439 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1440 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1442 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1443 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1444 xpc_release(xpc_array
);
1446 CFReleaseNull(array
);
1449 case kSecXPCOpOTAPKIGetNewAsset
:
1450 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1451 SecOTAPKISignalNewAsset(&error
));
1453 case kSecXPCOpRollKeys
:
1455 bool force
= xpc_dictionary_get_bool(event
, "force");
1456 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1457 _SecServerRollKeys(force
, &client
, &error
));
1460 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1462 CFDataRef cfbytes
= NULL
;
1463 const uint8_t *bytes
= NULL
;
1466 bytes
= xpc_dictionary_get_data(event
,
1467 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1469 SOSCreateError(kSOSErrorBadKey
,
1470 CFSTR("missing autoaccept info"), NULL
, &error
);
1474 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1476 SOSCreateError(kSOSErrorAllocationFailure
,
1477 CFSTR("could not allocate autoaccept info"),
1482 xpc_dictionary_set_bool(replyMessage
,
1484 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1488 case kSecXPCOpWaitForInitialSync
:
1489 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1490 SOSCCWaitForInitialSync_Server(&error
));
1493 case kSecXPCOpCopyYetToSyncViews
:
1495 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1497 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1498 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1499 xpc_release(xpc_array
);
1501 CFReleaseNull(array
);
1504 case kSecXPCOpSetEscrowRecord
:
1506 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1507 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1509 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1511 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1513 CFReleaseNull(escrow_label
);
1516 case kSecXPCOpGetEscrowRecord
:
1518 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1520 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1521 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1522 xpc_release(xpc_dictionary
);
1524 CFReleaseNull(record
);
1527 case kSecXPCOpCheckPeerAvailability
:
1529 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1532 case kSecXPCOpWhoAmI
:
1535 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1536 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1537 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1538 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1539 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1542 case kSecXPCOpTransmogrifyToSyncBubble
:
1544 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
)) {
1546 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1547 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1549 if (uid
&& services
) {
1550 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1552 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1553 CFReleaseNull(services
);
1555 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1559 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
);
1563 case kSecXPCOpTransmogrifyToSystemKeychain
:
1565 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
)) {
1567 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1568 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1570 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1574 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
);
1578 case kSecXPCOpDeleteUserView
:
1580 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
)) {
1583 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1585 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1588 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1591 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
);
1595 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1597 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1599 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1601 CFDataRef ciphertext
= NULL
;
1602 CFDataRef bskbEncoded
= NULL
;
1604 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1605 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1608 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, NULL
, 0);
1609 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, NULL
, 0);
1610 } else if(!result
) {
1611 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, NULL
, 0);
1612 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, NULL
, 0);
1615 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1618 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1622 CFReleaseSafe(plaintext
);
1624 CFReleaseNull(viewname
);
1635 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1636 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1637 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1638 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1640 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1642 xpcError
= SecCreateXPCObjectWithCFError(error
);
1644 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1646 } else if (replyMessage
) {
1647 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1650 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1651 secerror("%@: returning error: %@", client
.task
, error
);
1652 xpcError
= SecCreateXPCObjectWithCFError(error
);
1653 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1657 xpc_connection_send_message(connection
, replyMessage
);
1658 xpc_release(replyMessage
);
1661 xpc_release(xpcError
);
1662 pthread_setspecific(taskThreadKey
, NULL
);
1663 CFReleaseSafe(error
);
1664 CFReleaseSafe(client
.accessGroups
);
1665 CFReleaseSafe(client
.musr
);
1666 CFReleaseSafe(client
.task
);
1667 CFReleaseSafe(domains
);
1668 CFReleaseSafe(clientAuditToken
);
1671 static void securityd_xpc_init(const char *service_name
)
1673 pthread_key_create(&taskThreadKey
, NULL
);
1674 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1676 secdebug("serverxpc", "start");
1677 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1679 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1683 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1684 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1685 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1686 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1687 xpc_retain(connection
);
1689 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1690 securityd_xpc_dictionary_handler(connection
, event
);
1692 xpc_release(connection
);
1696 xpc_connection_resume(connection
);
1699 xpc_connection_resume(listener
);
1703 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1705 #if TARGET_OS_EMBEDDED
1706 static void securityd_soscc_lock_hack() {
1707 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1710 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1711 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1712 // this code will need to be generalized / migrated away from just this specific purpose.
1713 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1714 char *event_description
= xpc_copy_description(object
);
1715 secnotice("events", "%s", event_description
);
1716 free(event_description
);
1719 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1720 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1721 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1722 CFErrorRef error
= NULL
;
1724 uint64_t one_minute
= 60ull;
1725 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1726 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1727 xpc_transaction_begin();
1729 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1730 CFErrorRef localError
= NULL
;
1731 if(!SecAKSUnLockUserKeybag(&localError
))
1732 secerror("failed to unlock: %@", localError
);
1733 CFReleaseNull(localError
);
1734 xpc_transaction_end();
1737 secerror("Failed to take device lock assertion: %@", error
);
1739 CFReleaseSafe(error
);
1740 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1745 int main(int argc
, char *argv
[])
1747 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1748 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1749 seccritical("SIGSTOPing self, awaiting debugger");
1750 kill(getpid(), SIGSTOP
);
1751 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
1752 "Again, for good luck (or bad debuggers)");
1753 kill(getpid(), SIGSTOP
);
1756 const char *serviceName
= kSecuritydXPCServiceName
;
1758 serviceName
= kTrustdXPCServiceName
;
1759 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
1760 serviceName
= kTrustdAgentXPCServiceName
;
1763 securityd_init_server();
1764 securityd_xpc_init(serviceName
);
1766 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
1767 if (inMultiUser
== -1) {
1768 CFDictionaryRef deviceMode
= MKBUserTypeDeviceMode(NULL
, NULL
);
1769 CFTypeRef value
= NULL
;
1771 if (deviceMode
&& CFDictionaryGetValueIfPresent(deviceMode
, kMKBDeviceModeKey
, &value
) && CFEqual(value
, kMKBDeviceModeMultiUser
)) {
1776 CFReleaseNull(deviceMode
);
1778 #elif TARGET_OS_IPHONE
1782 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1783 #if TARGET_OS_EMBEDDED
1784 securityd_soscc_lock_hack();
1792 /* vi:set ts=4 sw=4 et: */