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/SecTrustInternal.h>
37 #include <Security/SecuritydXPC.h>
38 #include <securityd/OTATrustUtilities.h>
39 #include <securityd/SOSCloudCircleServer.h>
40 #include <securityd/SecItemBackupServer.h>
41 #include <securityd/SecItemServer.h>
42 #include <securityd/SecLogSettingsServer.h>
43 #include <securityd/SecOTRRemote.h>
44 #include <securityd/SecTrustServer.h>
45 #include <securityd/SecTrustStoreServer.h>
46 #include <securityd/iCloudTrace.h>
47 #include <securityd/spi.h>
48 #include <utilities/SecCFError.h>
49 #include <utilities/SecCFWrappers.h>
50 #include <utilities/SecDb.h>
51 #include <utilities/SecIOFormat.h>
52 #include <utilities/SecXPCError.h>
53 #include <utilities/debugging.h>
54 #include <utilities/SecInternalReleasePriv.h>
56 #include <AssertMacros.h>
57 #include <CoreFoundation/CFXPCBridge.h>
58 #include <CoreFoundation/CoreFoundation.h>
59 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
60 #if TARGET_OS_EMBEDDED
61 #include <MobileKeyBag/MobileKeyBag.h>
64 #include <Security/SecTaskPriv.h>
65 #include <login/SessionAgentStatusCom.h>
68 #include <bsm/libbsm.h>
69 #include <ipc/securityd_client.h>
70 #include <libkern/OSAtomic.h>
71 #include <mach/mach.h>
72 #include <mach/message.h>
75 #include <sys/queue.h>
76 #include <sys/sysctl.h>
78 #include <xpc/private.h>
82 static int inMultiUser
= 0;
86 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
87 CFStringRef entitlement
)
89 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
91 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
99 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
100 CFStringRef entitlement
)
102 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
105 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
106 CFIndex ix
, count
= CFArrayGetCount(value
);
107 for (ix
= 0; ix
< count
; ++ix
) {
108 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
109 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
124 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
125 return SecTaskCopyStringForEntitlement(task
,
126 kSecEntitlementApplicationIdentifier
);
129 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
130 return SecTaskCopyArrayOfStringsForEntitlement(task
,
131 kSecEntitlementAssociatedDomains
);
134 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
135 CFMutableArrayRef groups
= NULL
;
136 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
137 kSecEntitlementKeychainAccessGroups
);
138 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
139 kSecEntitlementAppleSecurityApplicationGroups
);
140 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
141 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
142 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
143 bool entitlementsValidated
= true;
144 bool hasEntitlements
= (kagLen
+ asagLen
+ (appID
? 1 : 0)) > 0;
145 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
146 entitlementsValidated
= SecTaskEntitlementsValidated(task
);
147 if ((appID
|| asagLen
) && !entitlementsValidated
) {
148 CFReleaseNull(appID
);
152 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
153 // Always allow access to com.apple.token access group, unless entitlement validation explicitly failed.
154 CFIndex tokenLen
= (!hasEntitlements
|| entitlementsValidated
) ? 1 : 0;
159 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
+ tokenLen
, &kCFTypeArrayCallBacks
);
161 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
163 CFArrayAppendValue(groups
, appID
);
165 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
167 CFArrayAppendValue(groups
, kSecAttrAccessGroupToken
);
168 #if TARGET_IPHONE_SIMULATOR
170 secwarning("No keychain access group specified while running in simulator, falling back to default set");
171 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
175 CFReleaseSafe(appID
);
176 CFReleaseSafe(keychainAccessGroups
);
177 CFReleaseSafe(appleSecurityApplicationGroups
);
182 static pthread_key_t taskThreadKey
;
183 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
184 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
188 CFErrorRef error
= NULL
;
189 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
190 kSecEntitlementApplicationIdentifier
,
191 kSecEntitlementKeychainAccessGroups
,
192 kSecEntitlementAppleSecurityApplicationGroups
,
194 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
195 CFReleaseNull(entitlementNames
);
197 // exclude some error types because they're accounted-for and not the reason we're here
198 if (rawEntitlements
== NULL
&& error
) {
199 CFErrorDomain domain
= CFErrorGetDomain(error
);
200 if (domain
&& CFEqual(domain
, kCFErrorDomainPOSIX
)) {
201 CFNumberRef code
= CFErrorGetCode(error
);
203 if (code
&& CFNumberGetValue(code
, kCFNumberIntType
, &errno
))
205 case ESRCH
: // no such process (bad pid or process died)
213 uint32_t cs_flags
= SecTaskGetCodeSignStatus(taskRef
);
214 CFStringRef identifier
= SecTaskCopySigningIdentifier(taskRef
, NULL
);
215 CFStringRef message
= NULL
;
217 if (rawEntitlements
== NULL
) { // NULL indicates failure-to-fetch (SecTask entitlements not initialized)
218 message
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("failed to fetch keychain client entitlements. task=%@ procid=%@ cs_flags=0x%08.8x error=%@"),
219 taskRef
, identifier
, cs_flags
, error
);
220 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
222 // non-NULL entitlement return => SecTaskCopyEntitlements succeeeded, no error
223 // but note that kernel EINVAL => no entitlements, no error to deal with unsigned code
224 message
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("found no keychain client entitlements. task=%@ procid=%@ cs_flags=0x%08.8x"),
225 taskRef
, identifier
, cs_flags
);
226 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
227 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
228 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
229 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
230 CFReleaseNull(newAccessGroups
);
232 char buffer
[1000] = "?";
233 CFStringGetCString(message
, buffer
, sizeof(buffer
), kCFStringEncodingUTF8
);
234 syslog(LOG_NOTICE
, "%s", buffer
);
235 __security_simulatecrash(message
, __sec_exception_code_MissingEntitlements
);
237 CFReleaseNull(rawEntitlements
);
238 CFReleaseNull(message
);
239 CFReleaseNull(identifier
);
240 CFReleaseNull(error
);
244 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
245 CFStringRef entitlement
) {
246 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
250 CFTypeID canModifyType
= CFGetTypeID(canModify
);
251 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
252 CFRelease(canModify
);
256 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
257 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
259 if (label_utf8
) { // Anything we would do here requires a user label
260 size_t password_length
= 0;
261 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
263 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
264 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
266 action(user_label
, user_password
);
268 CFReleaseNull(user_password
);
269 CFReleaseNull(user_label
);
273 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
274 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
276 if (label_utf8
) { // Anything we would do here requires a user label
277 size_t password_length
= 0;
278 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
279 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
281 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
282 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
283 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
285 action(user_label
, user_password
, dsid
);
288 CFReleaseNull(user_password
);
289 CFReleaseNull(user_label
);
293 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
294 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
295 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
296 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
298 action(user_label
, number
);
299 CFReleaseNull(user_label
);
302 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
305 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
309 xpc_dictionary_set_value(message
, key
, xpc_chain
);
310 xpc_release(xpc_chain
);
314 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
316 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
318 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
321 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
323 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
328 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
329 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
330 if (!xpc_certificates
)
331 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
332 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
333 return *certificates
;
336 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
337 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
338 if (!xpc_certificates
) {
339 *certificates
= NULL
;
342 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
343 return *certificates
;
346 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
347 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
353 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
354 return *policies
!= NULL
;
357 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
358 SecTrustStoreRef ts
= NULL
;
359 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
361 ts
= SecTrustStoreForDomainName(domain
, error
);
367 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
368 *pvalue
= xpc_dictionary_get_double(message
, key
);
369 if (*pvalue
== NAN
) {
370 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
375 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
376 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
379 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
380 CFDataRef data
= NULL
;
382 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
384 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
387 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
392 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
393 CFMutableArrayRef data_array
= NULL
;
394 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
395 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
396 size_t count
= xpc_array_get_count(xpc_data_array
);
397 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
398 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
401 for (ix
= 0; ix
< count
; ++ix
) {
402 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
404 CFRelease(data_array
);
407 CFArraySetValueAtIndex(data_array
, ix
, data
);
416 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
417 CFDataRef retval
= NULL
;
418 const uint8_t *bytes
= NULL
;
421 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
422 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
423 retval
= CFDataCreate(NULL
, bytes
, len
);
424 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
429 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
430 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
431 if (!xpc_data_array
) {
436 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
437 return *data_array
!= NULL
;
440 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
441 CFErrorRef error
= NULL
;
442 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
443 CFSetRef retval
= NULL
;
444 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
445 CFReleaseNull(error
);
450 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
452 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
453 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
454 xpc_release(xpc_array
);
456 CFReleaseNull(cf_array
);
460 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
463 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
465 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
466 xpc_release(xpc_array
);
471 CFReleaseNull(cf_array
);
476 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
479 if (fstat(fd
, &sb
) < 0) {
483 *size
= (size_t)sb
.st_size
;
484 if ((off_t
)*size
!= sb
.st_size
) {
488 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
489 if (*mem
== MAP_FAILED
) {
493 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
497 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
499 CFIndex count
= CFDataGetLength(data
);
500 const uint8_t *ptr
= CFDataGetBytePtr(data
);
501 bool writeResult
= false;
504 ssize_t ret
= write(fd
, ptr
, count
);
517 // Returns error if entitlement isn't present.
519 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
521 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
522 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
528 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
529 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
531 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
533 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
534 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
541 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
543 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
544 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
550 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
551 xpc_type_t type
= xpc_get_type(event
);
552 __block CFErrorRef error
= NULL
;
553 xpc_object_t xpcError
= NULL
;
554 xpc_object_t replyMessage
= NULL
;
555 CFDataRef clientAuditToken
= NULL
;
556 CFArrayRef domains
= NULL
;
557 SecurityClient client
= {
559 .accessGroups
= NULL
,
561 .uid
= xpc_connection_get_euid(connection
),
562 .allowSystemKeychain
= false,
563 .allowSyncBubbleKeychain
= false,
564 .isNetworkExtension
= false,
566 .inMultiUser
= inMultiUser
,
570 secdebug("serverxpc", "entering");
571 if (type
== XPC_TYPE_DICTIONARY
) {
572 // TODO: Find out what we're dispatching.
573 replyMessage
= xpc_dictionary_create_reply(event
);
575 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
577 client
.activeUser
= MKBForegroundUserSessionID(&error
);
578 if (client
.activeUser
== -1 || client
.activeUser
== 0) {
580 client
.activeUser
= 0;
584 * If we are a edu mode user, and its not the active user,
585 * then the request is coming from inside the syncbubble.
587 * otherwise we are going to execute the request as the
591 if (client
.uid
> 501 && (uid_t
)client
.activeUser
!= client
.uid
) {
592 secinfo("serverxpc", "securityd client: sync bubble user");
593 client
.musr
= SecMUSRCreateSyncBubbleUserUUID(client
.uid
);
594 client
.keybag
= KEYBAG_DEVICE
;
596 secinfo("serverxpc", "securityd client: active user");
597 client
.musr
= SecMUSRCreateActiveUserUUID(client
.activeUser
);
598 client
.uid
= (uid_t
)client
.activeUser
;
599 client
.keybag
= KEYBAG_DEVICE
;
604 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
606 audit_token_t auditToken
= {};
607 xpc_connection_get_audit_token(connection
, &auditToken
);
609 client
.task
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
610 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
612 pthread_setspecific(taskThreadKey
, client
.task
);
614 client
.accessGroups
= SecTaskCopyAccessGroups(client
.task
);
615 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
616 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
619 client
.allowSystemKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateSystemKeychain
);
620 client
.isNetworkExtension
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateNetworkExtension
);
622 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
623 if (client
.inMultiUser
) {
624 client
.allowSyncBubbleKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
);
627 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
633 case sec_item_add_id
:
635 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
636 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
638 CFTypeRef result
= NULL
;
639 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
640 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
641 CFReleaseNull(result
);
643 CFReleaseNull(query
);
648 case sec_item_copy_matching_id
:
650 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
651 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
653 CFTypeRef result
= NULL
;
654 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
655 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
656 CFReleaseNull(result
);
658 CFReleaseNull(query
);
663 case sec_item_update_id
:
665 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
666 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
668 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
669 if (attributesToUpdate
) {
670 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
671 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
672 CFReleaseNull(attributesToUpdate
);
674 CFReleaseNull(query
);
679 case sec_item_delete_id
:
681 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
682 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
684 bool result
= _SecItemDelete(query
, &client
, &error
);
685 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
686 CFReleaseNull(query
);
691 case sec_item_update_token_items_id
:
693 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
694 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
695 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
697 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
698 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
700 CFReleaseNull(tokenID
);
701 CFReleaseNull(attributes
);
705 case sec_trust_store_contains_id
:
707 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
709 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
712 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
713 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
714 CFReleaseNull(digest
);
719 case sec_trust_store_set_trust_settings_id
:
721 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
722 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
724 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
726 CFTypeRef trustSettingsDictOrArray
= NULL
;
727 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
728 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
729 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
730 CFReleaseSafe(trustSettingsDictOrArray
);
732 CFReleaseNull(certificate
);
738 case sec_trust_store_remove_certificate_id
:
740 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
741 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
743 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
745 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
746 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
747 CFReleaseNull(digest
);
753 case sec_trust_store_copy_all_id
:
755 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
756 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
758 CFArrayRef trustStoreContents
= NULL
;
759 if(_SecTrustStoreCopyAll(ts
, &trustStoreContents
, &error
) && trustStoreContents
) {
760 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, trustStoreContents
, &error
);
761 CFReleaseNull(trustStoreContents
);
767 case sec_trust_store_copy_usage_constraints_id
:
769 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
770 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
772 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
774 CFArrayRef usageConstraints
= NULL
;
775 if(_SecTrustStoreCopyUsageConstraints(ts
, digest
, &usageConstraints
, &error
) && usageConstraints
) {
776 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, usageConstraints
, &error
);
777 CFReleaseNull(usageConstraints
);
779 CFReleaseNull(digest
);
785 case sec_delete_all_id
:
786 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
788 #endif /* !TRUSTD_SERVER */
789 case sec_trust_evaluate_id
:
791 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
792 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
793 bool keychainsAllowed
= xpc_dictionary_get_bool(event
, kSecTrustKeychainsAllowedKey
);
795 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
796 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
797 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
798 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
799 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
800 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
801 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
802 // If we have no error yet, capture connection and reply in block and properly retain them.
803 xpc_retain(connection
);
804 CFRetainSafe(client
.task
);
805 CFRetainSafe(clientAuditToken
);
807 // Clear replyMessage so we don't send a synchronous reply.
808 xpc_object_t asyncReply
= replyMessage
;
811 SecTrustServerEvaluateBlock(clientAuditToken
,
812 certificates
, anchors
, anchorsOnly
, keychainsAllowed
, policies
, responses
, scts
, trustedLogs
, verifyTime
, client
.accessGroups
,
813 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
814 // Send back reply now
816 CFRetain(replyError
);
818 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
819 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
820 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
821 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
824 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
825 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
827 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
828 xpc_release(xpcReplyError
);
830 CFReleaseNull(replyError
);
832 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
835 xpc_connection_send_message(connection
, asyncReply
);
836 xpc_release(asyncReply
);
837 xpc_release(connection
);
838 CFReleaseSafe(client
.task
);
839 CFReleaseSafe(clientAuditToken
);
842 CFReleaseSafe(policies
);
843 CFReleaseSafe(anchors
);
844 CFReleaseSafe(certificates
);
845 CFReleaseSafe(responses
);
847 CFReleaseSafe(trustedLogs
);
851 case sec_keychain_backup_id
:
853 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
854 CFDataRef keybag
= NULL
, passcode
= NULL
;
855 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
856 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
857 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, &error
);
859 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
861 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
863 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
867 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
868 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
872 CFReleaseSafe(passcode
);
874 CFReleaseSafe(keybag
);
879 case sec_keychain_restore_id
:
881 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
882 CFDataRef backup
= NULL
;
886 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
888 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
890 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
893 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
895 CFDataRef passcode
= NULL
;
896 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
897 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
898 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
899 CFReleaseSafe(passcode
);
902 CFReleaseNull(keybag
);
904 CFReleaseNull(backup
);
913 case sec_keychain_backup_keybag_uuid_id
:
915 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
916 CFDataRef backup
= NULL
;
917 CFStringRef uuid
= NULL
;
921 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
923 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
925 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
928 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
930 CFReleaseNull(backup
);
940 case sec_keychain_sync_update_message_id
:
942 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
944 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
945 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
946 CFReleaseNull(result
);
948 CFReleaseNull(updates
);
951 case sec_keychain_backup_syncable_id
:
953 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
954 CFDictionaryRef oldbackup
= NULL
;
955 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
956 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
958 CFDataRef passcode
= NULL
;
959 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
960 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
962 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
963 CFRelease(newbackup
);
965 CFReleaseSafe(passcode
);
967 CFReleaseNull(keybag
);
969 CFReleaseSafe(oldbackup
);
974 case sec_keychain_restore_syncable_id
:
976 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
977 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
979 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
981 CFDataRef passcode
= NULL
;
982 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
983 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
984 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
985 CFReleaseSafe(passcode
);
987 CFReleaseNull(keybag
);
989 CFReleaseNull(backup
);
994 case sec_item_backup_copy_names_id
:
996 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
997 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
998 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
999 CFReleaseSafe(names
);
1003 case sec_item_backup_handoff_fd_id
:
1005 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1006 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1009 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
1010 CFRelease(backupName
);
1012 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
1018 case sec_item_backup_set_confirmed_manifest_id
:
1020 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1021 CFDataRef keybagDigest
= NULL
;
1022 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
1023 CFDataRef manifest
= NULL
;
1024 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
1025 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1027 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
1028 CFRelease(backupName
);
1029 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1031 CFReleaseSafe(manifest
);
1034 CFReleaseNull(keybagDigest
);
1038 case sec_item_backup_restore_id
:
1040 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1041 bool result
= false;
1042 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1044 CFStringRef peerID
= NULL
;
1045 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
1046 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1048 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
1050 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1052 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
1059 CFReleaseSafe(peerID
);
1061 CFRelease(backupName
);
1063 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1067 case sec_ota_pki_asset_version_id
:
1069 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1070 SecOTAPKIGetCurrentAssetVersion(&error
));
1073 case sec_add_shared_web_credential_id
:
1075 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1077 CFTypeRef result
= NULL
;
1078 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
1079 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
1080 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1081 CFReleaseNull(result
);
1083 CFReleaseSafe(appID
);
1084 CFReleaseNull(query
);
1088 case sec_copy_shared_web_credential_id
:
1090 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1092 CFTypeRef result
= NULL
;
1093 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
1094 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
1095 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1096 CFReleaseNull(result
);
1098 CFReleaseSafe(appID
);
1099 CFReleaseNull(query
);
1103 case sec_get_log_settings_id
:
1105 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
1107 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
1109 CFReleaseSafe(currentList
);
1112 case sec_set_xpc_log_settings_id
:
1114 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1116 SecSetXPCLogSettings_Server(newSettings
, &error
);
1118 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1119 CFReleaseNull(newSettings
);
1122 case sec_set_circle_log_settings_id
:
1124 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1126 SecSetCircleLogSettings_Server(newSettings
, &error
);
1128 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1129 CFReleaseNull(newSettings
);
1132 case sec_otr_session_create_remote_id
:
1134 CFDataRef publicPeerId
= NULL
;
1135 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
1136 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
1138 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
1139 CFReleaseNull(otrSession
);
1141 CFReleaseSafe(publicPeerId
);
1145 case sec_otr_session_process_packet_remote_id
:
1147 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
1148 bool readyForMessages
= false;
1149 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
1150 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
1151 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
1153 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
1154 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
1155 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
1156 CFReleaseNull(outputSessionData
);
1157 CFReleaseNull(outputPacket
);
1159 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1161 CFReleaseSafe(inputPacket
);
1163 CFReleaseSafe(sessionData
);
1167 case kSecXPCOpTryUserCredentials
:
1168 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1169 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1170 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1171 SOSCCTryUserCredentials_Server(label
, password
, &error
));
1175 case kSecXPCOpSetUserCredentials
:
1176 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1177 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1178 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1179 SOSCCSetUserCredentials_Server(label
, password
, &error
));
1183 case kSecXPCOpSetUserCredentialsAndDSID
:
1184 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1185 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
1186 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1187 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
1192 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1193 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
1194 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1195 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
1199 case kSecXPCOpViewSet
:
1200 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1201 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
1202 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
1203 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
1204 CFReleaseNull(enabledViews
);
1205 CFReleaseNull(disabledViews
);
1208 case kSecXPCOpSecurityProperty
:
1209 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1210 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
1211 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1212 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
1216 case kSecXPCOpCanAuthenticate
:
1217 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1218 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1219 SOSCCCanAuthenticate_Server(&error
));
1222 case kSecXPCOpPurgeUserCredentials
:
1223 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1224 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1225 SOSCCPurgeUserCredentials_Server(&error
));
1228 case kSecXPCOpDeviceInCircle
:
1229 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1230 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1231 SOSCCThisDeviceIsInCircle_Server(&error
));
1234 case kSecXPCOpRequestToJoin
:
1235 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1236 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1237 SOSCCRequestToJoinCircle_Server(&error
));
1240 case kSecXPCOpAccountHasPublicKey
:
1241 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1242 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1243 SOSCCAccountHasPublicKey_Server(&error
));
1246 case kSecXPCOpAccountIsNew
:
1247 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1248 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1249 SOSCCAccountIsNew_Server(&error
));
1252 case kSecXPCOpRequestToJoinAfterRestore
:
1253 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1254 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1255 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
1258 case kSecXPCOpRequestEnsureFreshParameters
:
1259 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1260 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1261 SOSCCRequestEnsureFreshParameters_Server(&error
));
1264 case kSecXPCOpGetAllTheRings
:
1265 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1266 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
1267 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
1268 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1269 xpc_release(xpc_dictionary
);
1272 case kSecXPCOpApplyToARing
:
1273 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1274 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1275 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
1276 CFReleaseNull(ringName
);
1279 case kSecXPCOpWithdrawlFromARing
:
1280 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1281 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1282 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
1283 CFReleaseNull(ringName
);
1286 case kSecXPCOpRingStatus
:
1287 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1288 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1289 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
1290 CFReleaseNull(ringName
);
1293 case kSecXPCOpEnableRing
:
1294 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1295 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1296 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
1297 CFReleaseNull(ringName
);
1300 case kSecXPCOpRequestDeviceID
:
1301 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1302 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
1304 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
1306 CFReleaseNull(deviceID
);
1309 case kSecXPCOpSetDeviceID
:
1310 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1311 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1312 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1316 case kSecXPCOpHandleIDSMessage
:
1317 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1318 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1319 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1324 case kSecXPCOpSendIDSMessage
:
1325 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1326 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1327 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1328 CFReleaseNull(message
);
1331 case kSecXPCOpSyncWithKVSPeer
:
1332 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1333 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1334 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVS(peerID
, &error
));
1335 CFReleaseNull(peerID
);
1338 case kSecXPCOpSyncWithIDSPeer
:
1339 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1340 CFStringRef deviceID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1341 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverIDS(deviceID
, &error
));
1342 CFReleaseNull(deviceID
);
1345 case kSecXPCOpPingTest
:
1346 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1347 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1348 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1349 CFReleaseNull(message
);
1352 case kSecXPCOpIDSDeviceID
:
1353 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1354 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1357 case kSecXPCOpAccountSetToNew
:
1358 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1359 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1362 case kSecXPCOpResetToOffering
:
1363 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1364 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1365 SOSCCResetToOffering_Server(&error
));
1368 case kSecXPCOpResetToEmpty
:
1369 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1370 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1371 SOSCCResetToEmpty_Server(&error
));
1374 case kSecXPCOpRemoveThisDeviceFromCircle
:
1375 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1376 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1377 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1380 case kSecXPCOpRemovePeersFromCircle
:
1381 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1382 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfos
, &error
);
1383 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1384 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1385 CFReleaseNull(applicants
);
1388 case kSecXPCOpLoggedOutOfAccount
:
1389 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1390 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1391 SOSCCLoggedOutOfAccount_Server(&error
));
1394 case kSecXPCOpBailFromCircle
:
1395 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1396 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1397 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1398 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1401 case kSecXPCOpAcceptApplicants
:
1402 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1403 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1404 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1405 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1406 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1407 CFReleaseSafe(applicants
);
1410 case kSecXPCOpRejectApplicants
:
1411 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1412 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1413 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1414 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1415 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1416 CFReleaseSafe(applicants
);
1419 case kSecXPCOpSetNewPublicBackupKey
:
1421 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1422 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1423 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1424 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1425 CFReleaseNull(peerInfo
);
1427 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1428 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1429 xpc_release(xpc_object
);
1431 CFReleaseNull(peerInfoData
);
1432 CFReleaseSafe(publicBackupKey
);
1437 case kSecXPCOpSetBagForAllSlices
:
1439 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1440 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1441 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1442 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1443 CFReleaseSafe(backupSlice
);
1447 case kSecXPCOpCopyApplicantPeerInfo
:
1448 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1449 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1450 SOSCCCopyApplicantPeerInfo_Server(&error
),
1454 case kSecXPCOpCopyValidPeerPeerInfo
:
1455 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1456 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1457 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1461 case kSecXPCOpValidateUserPublic
:
1462 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1463 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1464 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1467 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1468 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1469 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1470 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1474 case kSecXPCOpCopyGenerationPeerInfo
:
1475 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1476 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1477 SOSCCCopyGenerationPeerInfo_Server(&error
));
1480 case kSecXPCOpCopyRetirementPeerInfo
:
1481 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1482 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1483 SOSCCCopyRetirementPeerInfo_Server(&error
),
1487 case kSecXPCOpCopyViewUnawarePeerInfo
:
1488 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1489 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1490 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1494 case kSecXPCOpCopyAccountData
:
1496 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1497 xpc_object_t xpc_account_object
= NULL
;
1498 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1500 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1502 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1503 CFReleaseNull(accountData
);
1507 case kSecXPCOpDeleteAccountData
:
1509 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1510 bool status
= SOSCCDeleteAccountState_Server(&error
);
1511 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1515 case kSecXPCOpCopyEngineData
:
1517 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1519 xpc_object_t xpc_engine_object
= NULL
;
1520 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1522 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1524 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1525 CFReleaseNull(engineData
);
1530 case kSecXPCOpDeleteEngineData
:
1532 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1533 bool status
= SOSCCDeleteEngineState_Server(&error
);
1534 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1538 case kSecXPCOpCopyEngineState
:
1540 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1541 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1543 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1544 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1545 xpc_release(xpc_array
);
1547 CFReleaseNull(array
);
1551 case kSecXPCOpCopyPeerPeerInfo
:
1552 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1553 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1554 SOSCCCopyPeerPeerInfo_Server(&error
),
1558 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1559 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1560 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1561 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1565 case kSecXPCOpCopyMyPeerInfo
:
1566 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1567 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1568 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1569 CFReleaseNull(peerInfo
);
1571 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1572 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1573 xpc_release(xpc_object
);
1575 CFReleaseNull(peerInfoData
);
1578 case kSecXPCOpGetLastDepartureReason
:
1579 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1580 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1581 SOSCCGetLastDepartureReason_Server(&error
));
1584 case kSecXPCOpSetLastDepartureReason
:
1585 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1586 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1587 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1588 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1591 case kSecXPCOpProcessSyncWithAllPeers
:
1592 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1593 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1594 SOSCCProcessSyncWithAllPeers_Server(&error
));
1597 case soscc_EnsurePeerRegistration_id
:
1598 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1599 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1600 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1603 case kSecXPCOpCopyIncompatibilityInfo
:
1604 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1605 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1606 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1610 case kSecXPCOpOTAGetEscrowCertificates
:
1612 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1613 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1615 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1616 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1617 xpc_release(xpc_array
);
1619 CFReleaseNull(array
);
1622 case kSecXPCOpOTAPKIGetNewAsset
:
1623 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1624 SecOTAPKISignalNewAsset(&error
));
1626 case kSecXPCOpRollKeys
:
1628 bool force
= xpc_dictionary_get_bool(event
, "force");
1629 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1630 _SecServerRollKeys(force
, &client
, &error
));
1633 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1634 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1635 CFDataRef cfbytes
= NULL
;
1636 const uint8_t *bytes
= NULL
;
1639 bytes
= xpc_dictionary_get_data(event
,
1640 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1642 SOSCreateError(kSOSErrorBadKey
,
1643 CFSTR("missing autoaccept info"), NULL
, &error
);
1647 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1649 SOSCreateError(kSOSErrorAllocationFailure
,
1650 CFSTR("could not allocate autoaccept info"),
1655 xpc_dictionary_set_bool(replyMessage
,
1657 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1658 CFReleaseNull(cfbytes
);
1661 case kSecXPCOpWaitForInitialSync
:
1662 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1663 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1664 SOSCCWaitForInitialSync_Server(&error
));
1668 case kSecXPCOpCopyYetToSyncViews
:
1669 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1670 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1672 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1673 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1674 xpc_release(xpc_array
);
1676 CFReleaseNull(array
);
1679 case kSecXPCOpSetEscrowRecord
:
1680 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1681 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1682 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1684 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1686 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1688 CFReleaseNull(escrow_label
);
1691 case kSecXPCOpGetEscrowRecord
:
1692 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1693 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1695 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1696 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1697 xpc_release(xpc_dictionary
);
1699 CFReleaseNull(record
);
1702 case kSecXPCOpCheckPeerAvailability
:
1703 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1704 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1709 case kSecXPCOpIsThisDeviceLastBackup
:
1710 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1711 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1714 case kSecXPCOpPeersHaveViewsEnabled
:
1716 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1718 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1720 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1723 CFReleaseNull(viewSet
);
1727 case kSecXPCOpWhoAmI
:
1730 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1731 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1732 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1733 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1734 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1737 case kSecXPCOpTransmogrifyToSyncBubble
:
1739 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1741 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1742 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1744 if (uid
&& services
) {
1745 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1747 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1748 CFReleaseNull(services
);
1750 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1755 case kSecXPCOpTransmogrifyToSystemKeychain
:
1757 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1759 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1760 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1762 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1768 case kSecXPCOpDeleteUserView
:
1770 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1773 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1775 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1778 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1783 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1785 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1787 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1789 CFDataRef ciphertext
= NULL
;
1790 CFDataRef bskbEncoded
= NULL
;
1792 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1793 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1795 if(!error
&& result
) {
1797 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1800 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1803 CFReleaseSafe(ciphertext
);
1804 CFReleaseSafe(bskbEncoded
);
1806 CFReleaseSafe(plaintext
);
1808 CFReleaseNull(viewname
);
1811 case kSecXPCOpCopyApplication
:
1812 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1813 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1814 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1815 CFReleaseNull(peerInfo
);
1817 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1818 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1819 xpc_release(xpc_object
);
1821 CFReleaseNull(peerInfoData
);
1824 case kSecXPCOpCopyCircleJoiningBlob
:
1825 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1826 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1827 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1828 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1830 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1831 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1832 xpc_release(xpc_object
);
1834 CFReleaseNull(pbblob
);
1835 CFReleaseNull(applicant
);
1836 CFReleaseNull(appBlob
);
1839 case kSecXPCOpJoinWithCircleJoiningBlob
:
1840 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1841 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1843 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, &error
);
1844 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1845 CFReleaseNull(joiningBlob
);
1848 case sec_delete_items_with_access_groups_id
:
1850 bool retval
= false;
1851 #if TARGET_OS_IPHONE
1852 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1853 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1856 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1858 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1859 CFReleaseNull(accessGroups
);
1862 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1865 #endif /* !TRUSTD_SERVER */
1874 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1875 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1876 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1877 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1879 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1881 xpcError
= SecCreateXPCObjectWithCFError(error
);
1883 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1885 } else if (replyMessage
) {
1886 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1889 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1890 secerror("%@: returning error: %@", client
.task
, error
);
1891 xpcError
= SecCreateXPCObjectWithCFError(error
);
1892 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1896 xpc_connection_send_message(connection
, replyMessage
);
1897 xpc_release(replyMessage
);
1900 xpc_release(xpcError
);
1901 #if TARGET_OS_IPHONE
1902 pthread_setspecific(taskThreadKey
, NULL
);
1904 CFReleaseSafe(error
);
1905 CFReleaseSafe(client
.accessGroups
);
1906 CFReleaseSafe(client
.musr
);
1907 CFReleaseSafe(client
.task
);
1908 CFReleaseSafe(domains
);
1909 CFReleaseSafe(clientAuditToken
);
1912 static void securityd_xpc_init(const char *service_name
)
1914 #if TARGET_OS_IPHONE
1915 pthread_key_create(&taskThreadKey
, NULL
);
1916 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1919 secdebug("serverxpc", "start");
1920 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1922 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1926 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1927 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1928 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1929 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1930 xpc_retain(connection
);
1932 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1933 securityd_xpc_dictionary_handler(connection
, event
);
1935 xpc_release(connection
);
1939 xpc_connection_resume(connection
);
1942 xpc_connection_resume(listener
);
1946 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1948 #if TARGET_OS_EMBEDDED
1949 static void securityd_soscc_lock_hack() {
1950 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1953 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1954 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1955 // this code will need to be generalized / migrated away from just this specific purpose.
1956 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1957 char *event_description
= xpc_copy_description(object
);
1958 secnotice("events", "%s", event_description
);
1959 free(event_description
);
1962 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1963 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1964 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1965 CFErrorRef error
= NULL
;
1967 uint64_t one_minute
= 60ull;
1968 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1969 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1970 xpc_transaction_begin();
1972 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1973 CFErrorRef localError
= NULL
;
1974 if(!SecAKSUnLockUserKeybag(&localError
))
1975 secerror("failed to unlock: %@", localError
);
1976 CFReleaseNull(localError
);
1977 xpc_transaction_end();
1980 secerror("Failed to take device lock assertion: %@", error
);
1982 CFReleaseNull(error
);
1983 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1989 #include <trustd/SecTrustOSXEntryPoints.h>
1990 static void trustd_init_server(void) {
1991 SecTrustLegacySourcesEventRunloopCreate();
1995 int main(int argc
, char *argv
[])
1997 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1998 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1999 seccritical("SIGSTOPing self, awaiting debugger");
2000 kill(getpid(), SIGSTOP
);
2001 seccritical("Again, for good luck (or bad debuggers)");
2002 kill(getpid(), SIGSTOP
);
2005 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
2007 CFDictionaryRef deviceMode
= MKBUserTypeDeviceMode(NULL
, NULL
);
2008 CFTypeRef value
= NULL
;
2010 if (deviceMode
&& CFDictionaryGetValueIfPresent(deviceMode
, kMKBDeviceModeKey
, &value
) && CFEqual(value
, kMKBDeviceModeMultiUser
)) {
2013 CFReleaseNull(deviceMode
);
2017 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
2018 Secd doesn't realize DB connections get invalidated when network home directory users logout
2019 and their home gets unmounted. Exit secd, start fresh when user logs back in.
2021 #if !TARGET_OS_IPHONE
2022 int sessionstatechanged_tok
;
2023 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
2024 // we could be a process running as root.
2025 // However, since root never logs out this isn't an issue.
2026 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
2027 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
2028 xpc_transaction_exit_clean();
2034 const char *serviceName
= kSecuritydXPCServiceName
;
2036 serviceName
= kTrustdXPCServiceName
;
2037 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
2038 serviceName
= kTrustdAgentXPCServiceName
;
2041 /* setup SQDLite before some other component have a chance to create a database connection */
2042 _SecServerDatabaseSetup();
2044 securityd_init_server();
2046 trustd_init_server();
2048 securityd_xpc_init(serviceName
);
2050 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
2051 #if TARGET_OS_EMBEDDED
2052 securityd_soscc_lock_hack();
2060 /* vi:set ts=4 sw=4 et: */