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>
55 #include <utilities/der_plist.h>
56 #include <securityd/personalization.h>
58 #include <AssertMacros.h>
59 #include <CoreFoundation/CFXPCBridge.h>
60 #include <CoreFoundation/CoreFoundation.h>
61 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
63 #if __has_include(<MobileKeyBag/MobileKeyBag.h>) && TARGET_HAS_KEYSTORE
64 #include <MobileKeyBag/MobileKeyBag.h>
65 #define HAVE_MOBILE_KEYBAG_SUPPORT 1
68 #include <Security/SecTaskPriv.h>
69 #include <login/SessionAgentStatusCom.h>
72 #include <bsm/libbsm.h>
73 #include <ipc/securityd_client.h>
74 #include <libkern/OSAtomic.h>
75 #include <mach/mach.h>
76 #include <mach/message.h>
79 #include <sys/queue.h>
80 #include <sys/sysctl.h>
82 #include <xpc/private.h>
86 static int inMultiUser
= 0;
90 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
91 CFStringRef entitlement
)
93 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
95 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
103 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
104 CFStringRef entitlement
)
106 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
109 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
110 CFIndex ix
, count
= CFArrayGetCount(value
);
111 for (ix
= 0; ix
< count
; ++ix
) {
112 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
113 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
128 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
129 return SecTaskCopyStringForEntitlement(task
,
130 kSecEntitlementApplicationIdentifier
);
134 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
135 return SecTaskCopyArrayOfStringsForEntitlement(task
,
136 kSecEntitlementAssociatedDomains
);
140 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
141 CFMutableArrayRef groups
= NULL
;
142 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
143 kSecEntitlementKeychainAccessGroups
);
144 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
145 kSecEntitlementAppleSecurityApplicationGroups
);
146 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
147 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
148 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
149 bool entitlementsValidated
= true;
150 bool hasEntitlements
= (kagLen
+ asagLen
+ (appID
? 1 : 0)) > 0;
152 entitlementsValidated
= SecTaskEntitlementsValidated(task
);
153 if ((appID
|| asagLen
) && !entitlementsValidated
) {
154 CFReleaseNull(appID
);
158 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
159 // Always allow access to com.apple.token access group, unless entitlement validation explicitly failed.
160 CFIndex tokenLen
= (!hasEntitlements
|| entitlementsValidated
) ? 1 : 0;
165 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
+ tokenLen
, &kCFTypeArrayCallBacks
);
167 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
169 CFArrayAppendValue(groups
, appID
);
171 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
173 CFArrayAppendValue(groups
, kSecAttrAccessGroupToken
);
174 #if TARGET_IPHONE_SIMULATOR
176 secwarning("No keychain access group specified while running in simulator, falling back to default set");
177 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
181 CFReleaseSafe(appID
);
182 CFReleaseSafe(keychainAccessGroups
);
183 CFReleaseSafe(appleSecurityApplicationGroups
);
188 static pthread_key_t taskThreadKey
;
189 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
190 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
194 CFErrorRef error
= NULL
;
195 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
196 kSecEntitlementApplicationIdentifier
,
197 kSecEntitlementKeychainAccessGroups
,
198 kSecEntitlementAppleSecurityApplicationGroups
,
200 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
201 CFReleaseNull(entitlementNames
);
203 // exclude some error types because they're accounted-for and not the reason we're here
204 if (rawEntitlements
== NULL
&& error
) {
205 CFErrorDomain domain
= CFErrorGetDomain(error
);
206 if (domain
&& CFEqual(domain
, kCFErrorDomainPOSIX
)) {
207 CFIndex c
= CFErrorGetCode(error
);
211 case ESRCH
: // no such process (bad pid or process died)
219 uint32_t cs_flags
= SecTaskGetCodeSignStatus(taskRef
);
220 CFStringRef identifier
= SecTaskCopySigningIdentifier(taskRef
, NULL
);
221 CFStringRef message
= NULL
;
223 if (rawEntitlements
== NULL
) { // NULL indicates failure-to-fetch (SecTask entitlements not initialized)
224 message
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("failed to fetch keychain client entitlements. task=%@ procid=%@ cs_flags=0x%08.8x error=%@"),
225 taskRef
, identifier
, cs_flags
, error
);
226 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
228 // non-NULL entitlement return => SecTaskCopyEntitlements succeeeded, no error
229 // but note that kernel EINVAL => no entitlements, no error to deal with unsigned code
230 message
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("found no keychain client entitlements. task=%@ procid=%@ cs_flags=0x%08.8x"),
231 taskRef
, identifier
, cs_flags
);
232 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
233 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
234 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
235 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
236 CFReleaseNull(newAccessGroups
);
238 char buffer
[1000] = "?";
239 CFStringGetCString(message
, buffer
, sizeof(buffer
), kCFStringEncodingUTF8
);
240 syslog(LOG_NOTICE
, "%s", buffer
);
241 __security_simulatecrash(message
, __sec_exception_code_MissingEntitlements
);
243 CFReleaseNull(rawEntitlements
);
244 CFReleaseNull(message
);
245 CFReleaseNull(identifier
);
246 CFReleaseNull(error
);
250 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
251 CFStringRef entitlement
) {
252 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
256 CFTypeID canModifyType
= CFGetTypeID(canModify
);
257 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
258 CFRelease(canModify
);
263 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
264 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
266 if (label_utf8
) { // Anything we would do here requires a user label
267 size_t password_length
= 0;
268 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
270 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
271 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
273 action(user_label
, user_password
);
275 CFReleaseNull(user_password
);
276 CFReleaseNull(user_label
);
280 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
281 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
283 if (label_utf8
) { // Anything we would do here requires a user label
284 size_t password_length
= 0;
285 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
286 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
288 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
289 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
290 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
292 action(user_label
, user_password
, dsid
);
295 CFReleaseNull(user_password
);
296 CFReleaseNull(user_label
);
300 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
301 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
302 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
303 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
305 action(user_label
, number
);
306 CFReleaseNull(user_label
);
308 #endif /* !TRUSTD_SERVER */
310 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
313 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
317 xpc_dictionary_set_value(message
, key
, xpc_chain
);
318 xpc_release(xpc_chain
);
322 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
324 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
326 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
329 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
331 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
336 static bool SecXPCDictionaryCopyCertificates(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 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
340 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
341 return *certificates
;
344 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
345 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
346 if (!xpc_certificates
) {
347 *certificates
= NULL
;
350 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
351 return *certificates
;
354 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
355 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
361 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
362 return *policies
!= NULL
;
365 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
366 SecTrustStoreRef ts
= NULL
;
367 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
369 ts
= SecTrustStoreForDomainName(domain
, error
);
375 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
376 *pvalue
= xpc_dictionary_get_double(message
, key
);
377 if (*pvalue
== NAN
) {
378 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
383 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
384 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
387 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
388 CFDataRef data
= NULL
;
390 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
392 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
395 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
400 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
401 CFMutableArrayRef data_array
= NULL
;
402 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
403 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
404 size_t count
= xpc_array_get_count(xpc_data_array
);
405 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
406 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
409 for (ix
= 0; ix
< count
; ++ix
) {
410 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
412 CFRelease(data_array
);
415 CFArraySetValueAtIndex(data_array
, ix
, data
);
424 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
425 CFDataRef retval
= NULL
;
426 const uint8_t *bytes
= NULL
;
429 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
430 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
431 retval
= CFDataCreate(NULL
, bytes
, len
);
432 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
437 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
438 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
439 if (!xpc_data_array
) {
444 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
445 return *data_array
!= NULL
;
448 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
450 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
452 SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
);
454 return der
? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
458 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
459 CFErrorRef error
= NULL
;
460 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
461 CFSetRef retval
= NULL
;
462 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
463 CFReleaseNull(error
);
468 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
470 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
471 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
472 xpc_release(xpc_array
);
474 CFReleaseNull(cf_array
);
478 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
481 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
483 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
484 xpc_release(xpc_array
);
489 CFReleaseNull(cf_array
);
494 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
497 if (fstat(fd
, &sb
) < 0) {
501 *size
= (size_t)sb
.st_size
;
502 if ((off_t
)*size
!= sb
.st_size
) {
506 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
507 if (*mem
== MAP_FAILED
) {
511 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
515 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
517 CFIndex count
= CFDataGetLength(data
);
518 const uint8_t *ptr
= CFDataGetBytePtr(data
);
519 bool writeResult
= false;
522 ssize_t ret
= write(fd
, ptr
, count
);
535 // Returns error if entitlement isn't present.
537 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
539 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
540 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
546 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
547 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
549 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
551 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
552 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
559 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
561 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
562 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
568 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
569 xpc_type_t type
= xpc_get_type(event
);
570 __block CFErrorRef error
= NULL
;
571 xpc_object_t xpcError
= NULL
;
572 xpc_object_t replyMessage
= NULL
;
573 CFDataRef clientAuditToken
= NULL
;
574 CFArrayRef domains
= NULL
;
575 SecurityClient client
= {
577 .accessGroups
= NULL
,
579 .uid
= xpc_connection_get_euid(connection
),
580 .allowSystemKeychain
= false,
581 .allowSyncBubbleKeychain
= false,
582 .isNetworkExtension
= false,
584 .inMultiUser
= inMultiUser
,
588 secdebug("serverxpc", "entering");
589 if (type
== XPC_TYPE_DICTIONARY
) {
590 // TODO: Find out what we're dispatching.
591 replyMessage
= xpc_dictionary_create_reply(event
);
593 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
596 client
.activeUser
= MKBForegroundUserSessionID(&error
);
597 if (client
.activeUser
== -1 || client
.activeUser
== 0) {
599 client
.activeUser
= 0;
603 * If we are a edu mode user, and its not the active user,
604 * then the request is coming from inside the syncbubble.
606 * otherwise we are going to execute the request as the
610 if (client
.uid
> 501 && (uid_t
)client
.activeUser
!= client
.uid
) {
611 secinfo("serverxpc", "securityd client: sync bubble user");
612 client
.musr
= SecMUSRCreateSyncBubbleUserUUID(client
.uid
);
613 client
.keybag
= KEYBAG_DEVICE
;
615 secinfo("serverxpc", "securityd client: active user");
616 client
.musr
= SecMUSRCreateActiveUserUUID(client
.activeUser
);
617 client
.uid
= (uid_t
)client
.activeUser
;
618 client
.keybag
= KEYBAG_DEVICE
;
623 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
625 audit_token_t auditToken
= {};
626 xpc_connection_get_audit_token(connection
, &auditToken
);
628 client
.task
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
629 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
631 pthread_setspecific(taskThreadKey
, client
.task
);
633 client
.accessGroups
= SecTaskCopyAccessGroups(client
.task
);
636 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
637 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
642 client
.allowSystemKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateSystemKeychain
);
643 client
.isNetworkExtension
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateNetworkExtension
);
645 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
646 if (client
.inMultiUser
) {
647 client
.allowSyncBubbleKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
);
650 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
655 case sec_item_add_id
:
657 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
658 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
660 CFTypeRef result
= NULL
;
661 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
662 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
663 CFReleaseNull(result
);
665 CFReleaseNull(query
);
670 case sec_item_copy_matching_id
:
672 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
673 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
675 CFTypeRef result
= NULL
;
676 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
677 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
678 CFReleaseNull(result
);
680 CFReleaseNull(query
);
685 case sec_item_update_id
:
687 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
688 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
690 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
691 if (attributesToUpdate
) {
692 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
693 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
694 CFReleaseNull(attributesToUpdate
);
696 CFReleaseNull(query
);
701 case sec_item_delete_id
:
703 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
704 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
706 bool result
= _SecItemDelete(query
, &client
, &error
);
707 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
708 CFReleaseNull(query
);
713 case sec_item_update_token_items_id
:
715 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
716 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
717 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
719 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
720 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
722 CFReleaseNull(tokenID
);
723 CFReleaseNull(attributes
);
727 case sec_trust_store_contains_id
:
729 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
731 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
734 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
735 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
736 CFReleaseNull(digest
);
741 case sec_trust_store_set_trust_settings_id
:
743 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
744 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
746 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
748 CFTypeRef trustSettingsDictOrArray
= NULL
;
749 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
750 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
751 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
752 CFReleaseSafe(trustSettingsDictOrArray
);
754 CFReleaseNull(certificate
);
760 case sec_trust_store_remove_certificate_id
:
762 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
763 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
765 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
767 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
768 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
769 CFReleaseNull(digest
);
775 case sec_trust_store_copy_all_id
:
777 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
778 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
780 CFArrayRef trustStoreContents
= NULL
;
781 if(_SecTrustStoreCopyAll(ts
, &trustStoreContents
, &error
) && trustStoreContents
) {
782 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, trustStoreContents
, &error
);
783 CFReleaseNull(trustStoreContents
);
789 case sec_trust_store_copy_usage_constraints_id
:
791 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
)) {
792 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
794 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
796 CFArrayRef usageConstraints
= NULL
;
797 if(_SecTrustStoreCopyUsageConstraints(ts
, digest
, &usageConstraints
, &error
) && usageConstraints
) {
798 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, usageConstraints
, &error
);
799 CFReleaseNull(usageConstraints
);
801 CFReleaseNull(digest
);
807 case sec_delete_all_id
:
808 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
810 #endif /* !TRUSTD_SERVER */
811 case sec_trust_evaluate_id
:
813 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
814 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
815 bool keychainsAllowed
= xpc_dictionary_get_bool(event
, kSecTrustKeychainsAllowedKey
);
817 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
818 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
819 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
820 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
821 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
822 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
823 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
824 // If we have no error yet, capture connection and reply in block and properly retain them.
825 xpc_retain(connection
);
826 CFRetainSafe(client
.task
);
827 CFRetainSafe(clientAuditToken
);
829 // Clear replyMessage so we don't send a synchronous reply.
830 xpc_object_t asyncReply
= replyMessage
;
833 SecTrustServerEvaluateBlock(clientAuditToken
,
834 certificates
, anchors
, anchorsOnly
, keychainsAllowed
, policies
, responses
, scts
, trustedLogs
, verifyTime
, client
.accessGroups
,
835 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
836 // Send back reply now
838 CFRetain(replyError
);
840 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
841 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
842 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
843 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
846 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
847 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
849 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
850 xpc_release(xpcReplyError
);
852 CFReleaseNull(replyError
);
854 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
857 xpc_connection_send_message(connection
, asyncReply
);
858 xpc_release(asyncReply
);
859 xpc_release(connection
);
860 CFReleaseSafe(client
.task
);
861 CFReleaseSafe(clientAuditToken
);
864 CFReleaseSafe(policies
);
865 CFReleaseSafe(anchors
);
866 CFReleaseSafe(certificates
);
867 CFReleaseSafe(responses
);
869 CFReleaseSafe(trustedLogs
);
872 case sec_device_is_internal_id
:
874 bool retval
= SecIsDeviceInternal(NULL
);
875 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
879 case sec_keychain_backup_id
:
881 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
882 CFDataRef keybag
= NULL
, passcode
= NULL
;
883 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
884 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
885 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, &error
);
887 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
889 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
891 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
895 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
896 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
900 CFReleaseSafe(passcode
);
902 CFReleaseSafe(keybag
);
907 case sec_keychain_restore_id
:
909 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
910 CFDataRef backup
= NULL
;
914 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
916 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
918 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
921 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
923 CFDataRef passcode
= NULL
;
924 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
925 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
926 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
927 CFReleaseSafe(passcode
);
930 CFReleaseNull(keybag
);
932 CFReleaseNull(backup
);
941 case sec_keychain_backup_keybag_uuid_id
:
943 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
944 CFDataRef backup
= NULL
;
945 CFStringRef uuid
= NULL
;
949 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
951 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
953 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
956 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
958 CFReleaseNull(backup
);
968 case sec_keychain_sync_update_message_id
:
970 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
972 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
973 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
974 CFReleaseNull(result
);
976 CFReleaseNull(updates
);
979 case sec_keychain_backup_syncable_id
:
981 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
982 CFDictionaryRef oldbackup
= NULL
;
983 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
984 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
986 CFDataRef passcode
= NULL
;
987 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
988 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
990 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
991 CFRelease(newbackup
);
993 CFReleaseSafe(passcode
);
995 CFReleaseNull(keybag
);
997 CFReleaseSafe(oldbackup
);
1002 case sec_keychain_restore_syncable_id
:
1004 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1005 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
1007 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1009 CFDataRef passcode
= NULL
;
1010 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
1011 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
1012 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1013 CFReleaseSafe(passcode
);
1015 CFReleaseNull(keybag
);
1017 CFReleaseNull(backup
);
1022 case sec_item_backup_copy_names_id
:
1024 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1025 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
1026 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
1027 CFReleaseSafe(names
);
1031 case sec_item_backup_handoff_fd_id
:
1033 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1034 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1037 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
1038 CFRelease(backupName
);
1040 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
1046 case sec_item_backup_set_confirmed_manifest_id
:
1048 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1049 CFDataRef keybagDigest
= NULL
;
1050 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
1051 CFDataRef manifest
= NULL
;
1052 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
1053 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1055 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
1056 CFRelease(backupName
);
1057 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1059 CFReleaseSafe(manifest
);
1062 CFReleaseNull(keybagDigest
);
1066 case sec_item_backup_restore_id
:
1068 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1069 bool result
= false;
1070 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
1072 CFStringRef peerID
= NULL
;
1073 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
1074 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1076 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
1078 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1080 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
1087 CFReleaseSafe(peerID
);
1089 CFRelease(backupName
);
1091 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1095 case sec_ota_pki_asset_version_id
:
1097 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1098 SecOTAPKIGetCurrentAssetVersion(&error
));
1101 case sec_add_shared_web_credential_id
:
1104 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1106 CFTypeRef result
= NULL
;
1108 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
1109 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
1110 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1111 CFReleaseNull(result
);
1113 CFReleaseSafe(appID
);
1114 CFReleaseNull(query
);
1117 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
1121 case sec_copy_shared_web_credential_id
:
1124 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1126 CFTypeRef result
= NULL
;
1127 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
1128 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
1129 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1130 CFReleaseNull(result
);
1132 CFReleaseSafe(appID
);
1133 CFReleaseNull(query
);
1136 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
1140 case sec_get_log_settings_id
:
1142 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
1144 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
1146 CFReleaseSafe(currentList
);
1149 case sec_set_xpc_log_settings_id
:
1151 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1153 SecSetXPCLogSettings_Server(newSettings
, &error
);
1155 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1156 CFReleaseNull(newSettings
);
1159 case sec_set_circle_log_settings_id
:
1161 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1163 SecSetCircleLogSettings_Server(newSettings
, &error
);
1165 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1166 CFReleaseNull(newSettings
);
1169 case sec_otr_session_create_remote_id
:
1171 CFDataRef publicPeerId
= NULL
;
1172 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
1173 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
1175 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
1176 CFReleaseNull(otrSession
);
1178 CFReleaseSafe(publicPeerId
);
1182 case sec_otr_session_process_packet_remote_id
:
1184 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
1185 bool readyForMessages
= false;
1186 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
1187 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
1188 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
1190 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
1191 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
1192 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
1193 CFReleaseNull(outputSessionData
);
1194 CFReleaseNull(outputPacket
);
1196 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1198 CFReleaseSafe(inputPacket
);
1200 CFReleaseSafe(sessionData
);
1204 case kSecXPCOpTryUserCredentials
:
1205 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1206 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1207 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1208 SOSCCTryUserCredentials_Server(label
, password
, &error
));
1212 case kSecXPCOpSetUserCredentials
:
1213 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1214 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1215 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1216 SOSCCSetUserCredentials_Server(label
, password
, &error
));
1220 case kSecXPCOpSetUserCredentialsAndDSID
:
1221 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1222 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
1223 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1224 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
1229 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1230 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
1231 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1232 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
1236 case kSecXPCOpViewSet
:
1237 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1238 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
1239 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
1240 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
1241 CFReleaseNull(enabledViews
);
1242 CFReleaseNull(disabledViews
);
1245 case kSecXPCOpSecurityProperty
:
1246 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1247 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
1248 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1249 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
1253 case kSecXPCOpCanAuthenticate
:
1254 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1255 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1256 SOSCCCanAuthenticate_Server(&error
));
1259 case kSecXPCOpPurgeUserCredentials
:
1260 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1261 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1262 SOSCCPurgeUserCredentials_Server(&error
));
1265 case kSecXPCOpDeviceInCircle
:
1266 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1267 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1268 SOSCCThisDeviceIsInCircle_Server(&error
));
1271 case kSecXPCOpRequestToJoin
:
1272 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1273 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1274 SOSCCRequestToJoinCircle_Server(&error
));
1277 case kSecXPCOpAccountHasPublicKey
:
1278 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1279 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1280 SOSCCAccountHasPublicKey_Server(&error
));
1283 case kSecXPCOpAccountIsNew
:
1284 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1285 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1286 SOSCCAccountIsNew_Server(&error
));
1289 case kSecXPCOpRequestToJoinAfterRestore
:
1290 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1291 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1292 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
1295 case kSecXPCOpRequestEnsureFreshParameters
:
1296 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1297 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1298 SOSCCRequestEnsureFreshParameters_Server(&error
));
1301 case kSecXPCOpGetAllTheRings
:
1302 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1303 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
1304 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
1305 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1306 xpc_release(xpc_dictionary
);
1309 case kSecXPCOpApplyToARing
:
1310 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1311 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1312 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
1313 CFReleaseNull(ringName
);
1316 case kSecXPCOpWithdrawlFromARing
:
1317 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1318 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1319 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
1320 CFReleaseNull(ringName
);
1323 case kSecXPCOpRingStatus
:
1324 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1325 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1326 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
1327 CFReleaseNull(ringName
);
1330 case kSecXPCOpEnableRing
:
1331 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1332 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1333 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
1334 CFReleaseNull(ringName
);
1337 case kSecXPCOpRequestDeviceID
:
1338 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1339 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
1341 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
1343 CFReleaseNull(deviceID
);
1346 case kSecXPCOpSetDeviceID
:
1347 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1348 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1349 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1353 case kSecXPCOpHandleIDSMessage
:
1354 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1355 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1356 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1360 case kSecXPCOpClearKVSPeerMessage
:
1361 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1362 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1363 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCClearPeerMessageKeyInKVS_Server(peerID
, &error
));
1364 CFReleaseNull(peerID
);
1367 case kSecXPCOpSendIDSMessage
:
1368 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1369 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1370 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1371 CFReleaseNull(message
);
1374 case kSecXPCOpSyncWithKVSPeer
:
1375 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1376 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1377 CFDataRef message
= SecXPCDictionaryCopyData(event
, kSecXPCKeyIDSMessage
, &error
);
1378 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVS_Server(peerID
, message
, &error
));
1379 CFReleaseNull(peerID
);
1382 case kSecXPCOpSyncWithKVSPeerIDOnly
:
1383 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1384 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1385 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVSUsingIDOnly_Server(peerID
, &error
));
1386 CFReleaseNull(peerID
);
1389 case kSecXPCOpPingTest
:
1390 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1391 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1392 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1393 CFReleaseNull(message
);
1396 case kSecXPCOpIDSDeviceID
:
1397 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1398 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1401 case kSecXPCOpAccountSetToNew
:
1402 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1403 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1406 case kSecXPCOpResetToOffering
:
1407 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1408 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1409 SOSCCResetToOffering_Server(&error
));
1412 case kSecXPCOpResetToEmpty
:
1413 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1414 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1415 SOSCCResetToEmpty_Server(&error
));
1418 case kSecXPCOpRemoveThisDeviceFromCircle
:
1419 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1420 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1421 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1424 case kSecXPCOpRemovePeersFromCircle
:
1425 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1426 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1427 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1428 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1429 CFReleaseNull(applicants
);
1432 case kSecXPCOpLoggedOutOfAccount
:
1433 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1434 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1435 SOSCCLoggedOutOfAccount_Server(&error
));
1438 case kSecXPCOpBailFromCircle
:
1439 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1440 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1441 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1442 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1445 case kSecXPCOpAcceptApplicants
:
1446 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1447 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1448 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1449 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1450 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1451 CFReleaseSafe(applicants
);
1454 case kSecXPCOpRejectApplicants
:
1455 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1456 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1457 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1458 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1459 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1460 CFReleaseSafe(applicants
);
1463 case kSecXPCOpSetNewPublicBackupKey
:
1465 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1466 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1467 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1468 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1469 CFReleaseNull(peerInfo
);
1471 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1472 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1473 xpc_release(xpc_object
);
1475 CFReleaseNull(peerInfoData
);
1476 CFReleaseSafe(publicBackupKey
);
1481 case kSecXPCOpRegisterRecoveryPublicKey
:
1483 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1484 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1485 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1486 CFReleaseNull(recovery_key
);
1490 case kSecXPCOpGetRecoveryPublicKey
:
1492 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1493 xpc_object_t xpc_recovery_object
= NULL
;
1494 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1496 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1498 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1499 CFReleaseNull(recovery
);
1503 case kSecXPCOpSetBagForAllSlices
:
1505 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1506 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1507 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1508 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1509 CFReleaseSafe(backupSlice
);
1513 case kSecXPCOpCopyApplicantPeerInfo
:
1514 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1515 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1516 SOSCCCopyApplicantPeerInfo_Server(&error
),
1520 case kSecXPCOpCopyValidPeerPeerInfo
:
1521 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1522 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1523 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1527 case kSecXPCOpValidateUserPublic
:
1528 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1529 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1530 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1533 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1534 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1535 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1536 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1540 case kSecXPCOpCopyGenerationPeerInfo
:
1541 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1542 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1543 SOSCCCopyGenerationPeerInfo_Server(&error
));
1546 case kSecXPCOpCopyRetirementPeerInfo
:
1547 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1548 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1549 SOSCCCopyRetirementPeerInfo_Server(&error
),
1553 case kSecXPCOpCopyViewUnawarePeerInfo
:
1554 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1555 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1556 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1560 case kSecXPCOpCopyAccountData
:
1562 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1563 xpc_object_t xpc_account_object
= NULL
;
1564 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1566 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1568 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1569 CFReleaseNull(accountData
);
1573 case kSecXPCOpDeleteAccountData
:
1575 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1576 bool status
= SOSCCDeleteAccountState_Server(&error
);
1577 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1581 case kSecXPCOpCopyEngineData
:
1583 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1585 xpc_object_t xpc_engine_object
= NULL
;
1586 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1588 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1590 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1591 CFReleaseNull(engineData
);
1596 case kSecXPCOpDeleteEngineData
:
1598 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1599 bool status
= SOSCCDeleteEngineState_Server(&error
);
1600 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1604 case kSecXPCOpCopyEngineState
:
1606 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1607 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1608 CFDataRef derData
= NULL
;
1610 require_quiet(array
, done
);
1611 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1613 require_quiet(derData
, done
);
1614 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1616 CFReleaseNull(derData
);
1617 CFReleaseNull(array
);
1621 case kSecXPCOpCopyPeerPeerInfo
:
1622 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1623 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1624 SOSCCCopyPeerPeerInfo_Server(&error
),
1628 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1629 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1630 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1631 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1635 case kSecXPCOpCopyMyPeerInfo
:
1636 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1637 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1638 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1639 CFReleaseNull(peerInfo
);
1641 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1642 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1643 xpc_release(xpc_object
);
1645 CFReleaseNull(peerInfoData
);
1648 case kSecXPCOpGetLastDepartureReason
:
1649 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1650 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1651 SOSCCGetLastDepartureReason_Server(&error
));
1654 case kSecXPCOpSetLastDepartureReason
:
1655 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1656 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1657 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1658 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1661 case kSecXPCOpProcessSyncWithPeers
:
1662 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1663 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1664 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1665 if (peers
&& backupPeers
) {
1666 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1668 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1670 CFReleaseNull(result
);
1672 CFReleaseNull(peers
);
1673 CFReleaseNull(backupPeers
);
1676 case kSecXPCOpProcessSyncWithAllPeers
:
1677 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1678 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1679 SOSCCProcessSyncWithAllPeers_Server(&error
));
1682 case soscc_EnsurePeerRegistration_id
:
1683 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1684 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1685 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1688 case kSecXPCOpCopyIncompatibilityInfo
:
1689 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1690 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1691 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1695 case kSecXPCOpOTAGetEscrowCertificates
:
1697 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1698 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1700 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1701 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1702 xpc_release(xpc_array
);
1704 CFReleaseNull(array
);
1707 case kSecXPCOpOTAPKIGetNewAsset
:
1708 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1709 SecOTAPKISignalNewAsset(&error
));
1711 case kSecXPCOpRollKeys
:
1713 bool force
= xpc_dictionary_get_bool(event
, "force");
1714 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1715 _SecServerRollKeys(force
, &client
, &error
));
1718 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1719 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1720 CFDataRef cfbytes
= NULL
;
1721 const uint8_t *bytes
= NULL
;
1724 bytes
= xpc_dictionary_get_data(event
,
1725 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1727 SOSCreateError(kSOSErrorBadKey
,
1728 CFSTR("missing autoaccept info"), NULL
, &error
);
1732 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1734 SOSCreateError(kSOSErrorAllocationFailure
,
1735 CFSTR("could not allocate autoaccept info"),
1740 xpc_dictionary_set_bool(replyMessage
,
1742 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1743 CFReleaseNull(cfbytes
);
1746 case kSecXPCOpWaitForInitialSync
:
1747 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1748 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1749 SOSCCWaitForInitialSync_Server(&error
));
1753 case kSecXPCOpCopyYetToSyncViews
:
1754 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1755 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1757 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1758 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1759 xpc_release(xpc_array
);
1761 CFReleaseNull(array
);
1764 case kSecXPCOpSetEscrowRecord
:
1765 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1766 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1767 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1769 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1771 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1773 CFReleaseNull(escrow_label
);
1776 case kSecXPCOpGetEscrowRecord
:
1777 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1778 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1780 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1781 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1782 xpc_release(xpc_dictionary
);
1784 CFReleaseNull(record
);
1787 case kSecXPCOpCopyBackupInformation
:
1788 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1789 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1791 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1792 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1793 xpc_release(xpc_dictionary
);
1795 CFReleaseNull(record
);
1799 case kSecXPCOpCheckPeerAvailability
:
1800 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1801 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1806 case kSecXPCOpIsThisDeviceLastBackup
:
1807 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1808 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1811 case kSecXPCOpPeersHaveViewsEnabled
:
1813 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1815 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1817 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1820 CFReleaseNull(viewSet
);
1824 case kSecXPCOpWhoAmI
:
1827 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1828 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1829 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1830 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1831 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1834 case kSecXPCOpTransmogrifyToSyncBubble
:
1836 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1838 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1839 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1841 if (uid
&& services
) {
1842 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1844 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1845 CFReleaseNull(services
);
1847 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1852 case kSecXPCOpTransmogrifyToSystemKeychain
:
1854 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1856 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1857 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1859 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1865 case kSecXPCOpDeleteUserView
:
1867 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1870 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1872 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1875 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1880 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1882 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1884 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1886 CFDataRef ciphertext
= NULL
;
1887 CFDataRef bskbEncoded
= NULL
;
1889 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1890 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1892 if(!error
&& result
) {
1894 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1897 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1900 CFReleaseSafe(ciphertext
);
1901 CFReleaseSafe(bskbEncoded
);
1903 CFReleaseSafe(plaintext
);
1905 CFReleaseNull(viewname
);
1908 case kSecXPCOpCopyApplication
:
1909 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1910 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1911 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1912 CFReleaseNull(peerInfo
);
1914 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1915 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1916 xpc_release(xpc_object
);
1918 CFReleaseNull(peerInfoData
);
1921 case kSecXPCOpCopyCircleJoiningBlob
:
1922 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1923 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1924 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1925 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1927 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1928 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1929 xpc_release(xpc_object
);
1931 CFReleaseNull(pbblob
);
1932 CFReleaseNull(applicant
);
1933 CFReleaseNull(appBlob
);
1936 case kSecXPCOpJoinWithCircleJoiningBlob
:
1937 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1938 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1940 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, &error
);
1941 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1942 CFReleaseNull(joiningBlob
);
1945 case kSecXPCOpMessageFromPeerIsPending
:
1947 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1949 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1950 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1952 CFReleaseNull(peer
);
1955 case kSecXPCOpSendToPeerIsPending
:
1957 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1959 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1960 SOSCCSendToPeerIsPending(peer
, &error
));
1962 CFReleaseNull(peer
);
1965 case sec_delete_items_with_access_groups_id
:
1967 bool retval
= false;
1968 #if TARGET_OS_IPHONE
1969 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1970 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1973 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1975 CFReleaseNull(accessGroups
);
1978 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1981 #endif /* !TRUSTD_SERVER */
1988 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1989 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1990 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1991 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1993 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1995 xpcError
= SecCreateXPCObjectWithCFError(error
);
1997 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1999 } else if (replyMessage
) {
2000 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
2003 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
2004 secerror("%@: returning error: %@", client
.task
, error
);
2005 xpcError
= SecCreateXPCObjectWithCFError(error
);
2006 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
2010 xpc_connection_send_message(connection
, replyMessage
);
2011 xpc_release(replyMessage
);
2014 xpc_release(xpcError
);
2015 #if TARGET_OS_IPHONE
2016 pthread_setspecific(taskThreadKey
, NULL
);
2018 CFReleaseSafe(error
);
2019 CFReleaseSafe(client
.accessGroups
);
2020 CFReleaseSafe(client
.musr
);
2021 CFReleaseSafe(client
.task
);
2022 CFReleaseSafe(domains
);
2023 CFReleaseSafe(clientAuditToken
);
2026 static void securityd_xpc_init(const char *service_name
)
2028 #if TARGET_OS_IPHONE
2029 pthread_key_create(&taskThreadKey
, NULL
);
2030 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
2033 secdebug("serverxpc", "start");
2034 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
2036 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
2040 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
2041 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
2042 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
2043 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
2044 xpc_retain(connection
);
2046 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
2047 securityd_xpc_dictionary_handler(connection
, event
);
2049 xpc_release(connection
);
2053 xpc_connection_resume(connection
);
2056 xpc_connection_resume(listener
);
2060 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
2062 #if TARGET_OS_EMBEDDED
2063 static void securityd_soscc_lock_hack() {
2064 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
2067 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
2068 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
2069 // this code will need to be generalized / migrated away from just this specific purpose.
2070 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
2071 char *event_description
= xpc_copy_description(object
);
2072 secnotice("events", "%s", event_description
);
2073 free(event_description
);
2076 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
2077 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
2078 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
2079 CFErrorRef error
= NULL
;
2081 uint64_t one_minute
= 60ull;
2082 if(SecAKSLockUserKeybag(one_minute
, &error
)){
2083 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
2084 xpc_transaction_begin();
2086 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
2087 CFErrorRef localError
= NULL
;
2088 if(!SecAKSUnLockUserKeybag(&localError
))
2089 secerror("failed to unlock: %@", localError
);
2090 CFReleaseNull(localError
);
2091 xpc_transaction_end();
2094 secerror("Failed to take device lock assertion: %@", error
);
2096 CFReleaseNull(error
);
2097 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
2103 #include <trustd/SecTrustOSXEntryPoints.h>
2104 static void trustd_init_server(void) {
2105 SecTrustLegacySourcesEventRunloopCreate();
2109 int main(int argc
, char *argv
[])
2111 char *wait4debugger
= getenv("WAIT4DEBUGGER");
2112 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
2113 seccritical("SIGSTOPing self, awaiting debugger");
2114 kill(getpid(), SIGSTOP
);
2115 seccritical("Again, for good luck (or bad debuggers)");
2116 kill(getpid(), SIGSTOP
);
2119 #if HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_EMBEDDED
2121 CFDictionaryRef deviceMode
= MKBUserTypeDeviceMode(NULL
, NULL
);
2122 CFTypeRef value
= NULL
;
2124 if (deviceMode
&& CFDictionaryGetValueIfPresent(deviceMode
, kMKBDeviceModeKey
, &value
) && CFEqual(value
, kMKBDeviceModeMultiUser
)) {
2127 CFReleaseNull(deviceMode
);
2131 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
2132 Secd doesn't realize DB connections get invalidated when network home directory users logout
2133 and their home gets unmounted. Exit secd, start fresh when user logs back in.
2135 #if !TARGET_OS_IPHONE
2136 int sessionstatechanged_tok
;
2137 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
2138 // we could be a process running as root.
2139 // However, since root never logs out this isn't an issue.
2140 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
2141 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
2142 xpc_transaction_exit_clean();
2148 const char *serviceName
= kSecuritydXPCServiceName
;
2150 serviceName
= kTrustdXPCServiceName
;
2151 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
2152 serviceName
= kTrustdAgentXPCServiceName
;
2155 /* setup SQDLite before some other component have a chance to create a database connection */
2156 _SecServerDatabaseSetup();
2158 securityd_init_server();
2160 trustd_init_server();
2162 securityd_xpc_init(serviceName
);
2164 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
2165 #if TARGET_OS_EMBEDDED
2166 securityd_soscc_lock_hack();
2172 /* vi:set ts=4 sw=4 et: */