2 * Copyright (c) 2007-2015 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecureObjectSync/SOSPeerInfoDER.h>
25 #include <Security/SecureObjectSync/SOSCloudCircle.h>
26 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27 #include <Security/SecureObjectSync/SOSInternal.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecEntitlements.h>
32 #include <Security/SecInternal.h>
33 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
34 #include <Security/SecPolicyInternal.h>
35 #include <Security/SecTask.h>
36 #include <Security/SecuritydXPC.h>
37 #include <securityd/OTATrustUtilities.h>
38 #include <securityd/SOSCloudCircleServer.h>
39 #include <securityd/SecItemBackupServer.h>
40 #include <securityd/SecItemServer.h>
41 #include <securityd/SecLogSettingsServer.h>
42 #include <securityd/SecOTRRemote.h>
43 #include <securityd/SecTrustServer.h>
44 #include <securityd/SecTrustStoreServer.h>
45 #include <securityd/iCloudTrace.h>
46 #include <securityd/spi.h>
47 #include <utilities/SecCFError.h>
48 #include <utilities/SecCFWrappers.h>
49 #include <utilities/SecDb.h>
50 #include <utilities/SecIOFormat.h>
51 #include <utilities/SecXPCError.h>
52 #include <utilities/debugging.h>
53 #include <utilities/SecInternalReleasePriv.h>
55 #include <AssertMacros.h>
56 #include <CoreFoundation/CFXPCBridge.h>
57 #include <CoreFoundation/CoreFoundation.h>
58 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
59 #if TARGET_OS_EMBEDDED
60 #include <MobileKeyBag/MobileKeyBag.h>
63 #include <Security/SecTaskPriv.h>
66 #include <bsm/libbsm.h>
67 #include <ipc/securityd_client.h>
68 #include <libkern/OSAtomic.h>
69 #include <mach/mach.h>
70 #include <mach/message.h>
73 #include <sys/queue.h>
74 #include <sys/sysctl.h>
76 #include <xpc/private.h>
80 static int inMultiUser
= 0;
84 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
85 CFStringRef entitlement
)
87 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
89 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
97 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
98 CFStringRef entitlement
)
100 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
103 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
104 CFIndex ix
, count
= CFArrayGetCount(value
);
105 for (ix
= 0; ix
< count
; ++ix
) {
106 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
107 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
122 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
123 return SecTaskCopyStringForEntitlement(task
,
124 kSecEntitlementApplicationIdentifier
);
127 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
128 return SecTaskCopyArrayOfStringsForEntitlement(task
,
129 kSecEntitlementAssociatedDomains
);
132 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
133 CFMutableArrayRef groups
= NULL
;
134 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
135 kSecEntitlementKeychainAccessGroups
);
136 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
137 kSecEntitlementAppleSecurityApplicationGroups
);
138 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
139 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
140 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
141 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
142 if ((appID
|| asagLen
) && !SecTaskEntitlementsValidated(task
)) {
143 CFReleaseNull(appID
);
147 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
149 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
);
151 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
153 CFArrayAppendValue(groups
, appID
);
155 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
156 #if TARGET_IPHONE_SIMULATOR
158 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
159 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
163 CFReleaseSafe(appID
);
164 CFReleaseSafe(keychainAccessGroups
);
165 CFReleaseSafe(appleSecurityApplicationGroups
);
169 static pthread_key_t taskThreadKey
;
170 static void secTaskDiagnoseEntitlements(CFArrayRef accessGroups
) {
171 SecTaskRef taskRef
= pthread_getspecific(taskThreadKey
);
172 if (taskRef
== NULL
) {
173 secerror("MISSING keychain entitlements: no stored taskRef found");
177 CFErrorRef error
= NULL
;
178 CFArrayRef entitlementNames
= CFArrayCreateForCFTypes(NULL
,
179 kSecEntitlementApplicationIdentifier
,
180 kSecEntitlementKeychainAccessGroups
,
181 kSecEntitlementAppleSecurityApplicationGroups
,
183 CFDictionaryRef rawEntitlements
= SecTaskCopyValuesForEntitlements(taskRef
, entitlementNames
, &error
);
184 CFRelease(entitlementNames
);
186 if (rawEntitlements
== NULL
) {
187 secerror("MISSING keychain entitlements: retrieve-entitlements error %@", error
);
188 CFReleaseSafe(error
);
189 __security_simulatecrash(CFSTR("failed to read keychain client entitlement(s)"), __sec_exception_code_MissingEntitlements
);
193 secerror("MISSING keychain entitlements: raw entitlement values: %@", rawEntitlements
);
194 secerror("MISSING keychain entitlements: original ag: %@", accessGroups
);
195 CFArrayRef newAccessGroups
= SecTaskCopyAccessGroups(taskRef
);
196 secerror("MISSING keychain entitlements: newly parsed ag: %@", newAccessGroups
);
198 __security_simulatecrash(CFSTR("keychain entitlement(s) missing"), __sec_exception_code_MissingEntitlements
);
200 CFReleaseSafe(newAccessGroups
);
201 CFReleaseSafe(rawEntitlements
);
204 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
205 CFStringRef entitlement
) {
206 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
210 CFTypeID canModifyType
= CFGetTypeID(canModify
);
211 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
212 CFRelease(canModify
);
216 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
217 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
219 if (label_utf8
) { // Anything we would do here requires a user label
220 size_t password_length
= 0;
221 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
223 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
224 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
226 action(user_label
, user_password
);
228 CFReleaseNull(user_password
);
229 CFReleaseNull(user_label
);
233 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
234 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
236 if (label_utf8
) { // Anything we would do here requires a user label
237 size_t password_length
= 0;
238 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
239 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
241 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
242 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
243 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
245 action(user_label
, user_password
, dsid
);
248 CFReleaseNull(user_password
);
249 CFReleaseNull(user_label
);
253 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
254 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
255 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
256 secnotice("views", "Action Code Raw is %d", (int) number
);
257 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
259 action(user_label
, number
);
260 CFReleaseNull(user_label
);
263 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
266 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
270 xpc_dictionary_set_value(message
, key
, xpc_chain
);
271 xpc_release(xpc_chain
);
275 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
277 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
279 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
282 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
284 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
289 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
290 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
291 if (!xpc_certificates
)
292 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
293 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
294 return *certificates
;
297 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
298 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
299 if (!xpc_certificates
) {
300 *certificates
= NULL
;
303 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
304 return *certificates
;
307 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
308 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
314 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
315 return *policies
!= NULL
;
318 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
319 SecTrustStoreRef ts
= NULL
;
320 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
322 ts
= SecTrustStoreForDomainName(domain
, error
);
328 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
329 *pvalue
= xpc_dictionary_get_double(message
, key
);
330 if (*pvalue
== NAN
) {
331 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
336 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
337 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
340 static CFDataRef
CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array
, size_t index
, CFErrorRef
*error
) {
341 CFDataRef data
= NULL
;
343 const uint8_t *bytes
= xpc_array_get_data(xpc_data_array
, index
, &length
);
345 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, length
);
348 SecError(errSecParam
, error
, CFSTR("data_array[%zu] failed to decode"), index
);
353 static CFArrayRef
CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array
, CFErrorRef
*error
) {
354 CFMutableArrayRef data_array
= NULL
;
355 require_action_quiet(xpc_get_type(xpc_data_array
) == XPC_TYPE_ARRAY
, exit
,
356 SecError(errSecParam
, error
, CFSTR("data_array xpc value is not an array")));
357 size_t count
= xpc_array_get_count(xpc_data_array
);
358 require_action_quiet(data_array
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
), exit
,
359 SecError(errSecAllocate
, error
, CFSTR("failed to create CFArray of capacity %zu"), count
));
362 for (ix
= 0; ix
< count
; ++ix
) {
363 CFDataRef data
= CFDataCreateWithXPCArrayAtIndex(xpc_data_array
, ix
, error
);
365 CFRelease(data_array
);
368 CFArraySetValueAtIndex(data_array
, ix
, data
);
376 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message
, const char *key
, CFArrayRef
*data_array
, CFErrorRef
*error
) {
377 xpc_object_t xpc_data_array
= xpc_dictionary_get_value(message
, key
);
378 if (!xpc_data_array
) {
383 *data_array
= CFDataXPCArrayCopyArray(xpc_data_array
, error
);
384 return *data_array
!= NULL
;
387 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
388 CFErrorRef error
= NULL
;
389 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
390 CFSetRef retval
= NULL
;
391 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
392 CFReleaseNull(error
);
397 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
399 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
400 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
401 xpc_release(xpc_array
);
403 CFReleaseNull(cf_array
);
407 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
410 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
412 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
413 xpc_release(xpc_array
);
418 CFReleaseNull(cf_array
);
423 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
426 if (fstat(fd
, &sb
) < 0) {
430 *size
= (size_t)sb
.st_size
;
431 if ((off_t
)*size
!= sb
.st_size
) {
435 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
436 if (*mem
== MAP_FAILED
) {
440 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
444 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
446 CFIndex count
= CFDataGetLength(data
);
447 const uint8_t *ptr
= CFDataGetBytePtr(data
);
448 bool writeResult
= false;
451 ssize_t ret
= write(fd
, ptr
, count
);
466 EntitlementMissing(enum SecXPCOperation op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
468 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription(op
), clientTask
, entitlement
);
473 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
474 xpc_type_t type
= xpc_get_type(event
);
475 __block CFErrorRef error
= NULL
;
476 xpc_object_t xpcError
= NULL
;
477 xpc_object_t replyMessage
= NULL
;
478 CFDataRef clientAuditToken
= NULL
;
479 CFArrayRef domains
= NULL
;
480 SecurityClient client
= {
482 .accessGroups
= NULL
,
484 .uid
= xpc_connection_get_euid(connection
),
485 .allowSystemKeychain
= false,
486 .allowSyncBubbleKeychain
= false,
487 .isNetworkExtension
= false,
489 .inMultiUser
= inMultiUser
,
493 secdebug("serverxpc", "entering");
494 if (type
== XPC_TYPE_DICTIONARY
) {
495 // TODO: Find out what we're dispatching.
496 replyMessage
= xpc_dictionary_create_reply(event
);
498 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
500 client
.activeUser
= MKBForegroundUserSessionID(&error
);
501 if (client
.activeUser
== -1 || client
.activeUser
== 0) {
503 client
.activeUser
= 0;
507 * If we are a edu mode user, and its not the active user,
508 * then the request is coming from inside the syncbubble.
510 * otherwise we are going to execute the request as the
514 if (client
.uid
> 501 && (uid_t
)client
.activeUser
!= client
.uid
) {
515 secinfo("serverxpc", "securityd client: sync bubble user");
516 client
.musr
= SecMUSRCreateSyncBubbleUserUUID(client
.uid
);
517 client
.keybag
= KEYBAG_DEVICE
;
519 secinfo("serverxpc", "securityd client: active user");
520 client
.musr
= SecMUSRCreateActiveUserUUID(client
.activeUser
);
521 client
.uid
= (uid_t
)client
.activeUser
;
522 client
.keybag
= KEYBAG_DEVICE
;
527 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
530 audit_token_t auditToken
= {};
531 xpc_connection_get_audit_token(connection
, &auditToken
);
533 client
.task
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
534 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
535 pthread_setspecific(taskThreadKey
, client
.task
);
536 client
.accessGroups
= SecTaskCopyAccessGroups(client
.task
);
537 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
538 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
541 client
.allowSystemKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateSystemKeychain
);
542 client
.isNetworkExtension
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateNetworkExtension
);
544 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
545 if (client
.inMultiUser
) {
546 client
.allowSyncBubbleKeychain
= SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
);
550 // TODO: change back to secdebug
551 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
554 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
555 // Refer to rdar://problem/18615626&18616300 for more details.
556 int64_t minimumDirtyInterval
= (int64_t) (2 * NSEC_PER_SEC
);
557 xpc_transaction_begin();
558 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, minimumDirtyInterval
), dispatch_get_main_queue(), ^{
559 xpc_transaction_end();
563 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
564 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
565 (client
.task
&& SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
));
567 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
568 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
570 if (!hasEntitlement
) {
571 CFErrorRef entitlementError
= NULL
;
572 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
);
573 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
574 CFReleaseSafe(entitlementError
);
580 case sec_item_add_id
:
582 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
584 CFTypeRef result
= NULL
;
585 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
586 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
593 case sec_item_copy_matching_id
:
595 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
597 CFTypeRef result
= NULL
;
598 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
599 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
606 case sec_item_update_id
:
608 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
610 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
611 if (attributesToUpdate
) {
612 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
613 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
614 CFRelease(attributesToUpdate
);
620 case sec_item_delete_id
:
622 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
624 bool result
= _SecItemDelete(query
, &client
, &error
);
625 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
630 case sec_trust_store_contains_id
:
632 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
634 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
637 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
638 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
644 case sec_trust_store_set_trust_settings_id
:
646 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementModifyAnchorCertificates
)) {
647 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
649 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
651 CFTypeRef trustSettingsDictOrArray
= NULL
;
652 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
653 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
654 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
655 CFReleaseSafe(trustSettingsDictOrArray
);
657 CFRelease(certificate
);
661 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
);
665 case sec_trust_store_remove_certificate_id
:
667 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementModifyAnchorCertificates
)) {
668 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
670 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
672 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
673 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
678 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementModifyAnchorCertificates
, &error
);
682 case sec_delete_all_id
:
683 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
685 case sec_trust_evaluate_id
:
687 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
, responses
= NULL
, scts
= NULL
, trustedLogs
= NULL
;
688 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
690 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
691 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
692 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
693 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustResponsesKey
, &responses
, &error
) &&
694 SecXPCDictionaryCopyCFDataArrayOptional(event
, kSecTrustSCTsKey
, &scts
, &error
) &&
695 SecXPCDictionaryCopyArrayOptional(event
, kSecTrustTrustedLogsKey
, &trustedLogs
, &error
) &&
696 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
697 // If we have no error yet, capture connection and reply in block and properly retain them.
698 xpc_retain(connection
);
699 CFRetainSafe(client
.task
);
700 CFRetainSafe(clientAuditToken
);
702 // Clear replyMessage so we don't send a synchronous reply.
703 xpc_object_t asyncReply
= replyMessage
;
706 SecTrustServerEvaluateBlock(clientAuditToken
,
707 certificates
, anchors
, anchorsOnly
, policies
, responses
, scts
, trustedLogs
, verifyTime
, client
.accessGroups
,
708 ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
709 // Send back reply now
711 CFRetain(replyError
);
713 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
714 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
715 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
716 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
719 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
720 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
722 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
723 xpc_release(xpcReplyError
);
725 CFRelease(replyError
);
727 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
730 xpc_connection_send_message(connection
, asyncReply
);
731 xpc_release(asyncReply
);
732 xpc_release(connection
);
733 CFReleaseSafe(client
.task
);
734 CFReleaseSafe(clientAuditToken
);
737 CFReleaseSafe(policies
);
738 CFReleaseSafe(anchors
);
739 CFReleaseSafe(certificates
);
740 CFReleaseSafe(responses
);
742 CFReleaseSafe(trustedLogs
);
745 case sec_keychain_backup_id
:
747 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
748 CFDataRef keybag
= NULL
, passcode
= NULL
;
749 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
750 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
751 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, &error
);
753 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
755 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
757 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
761 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
762 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
766 CFReleaseSafe(passcode
);
768 CFReleaseSafe(keybag
);
771 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
775 case sec_keychain_restore_id
:
777 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
778 CFDataRef backup
= NULL
;
782 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
784 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
786 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
789 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
791 CFDataRef passcode
= NULL
;
792 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
793 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
794 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
795 CFReleaseSafe(passcode
);
805 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
809 case sec_keychain_sync_update_message_id
:
811 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
813 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
814 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
815 CFReleaseNull(result
);
817 CFReleaseNull(updates
);
820 case sec_keychain_backup_syncable_id
:
822 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
824 CFDictionaryRef oldbackup
= NULL
;
825 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
826 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
828 CFDataRef passcode
= NULL
;
829 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
830 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
832 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
833 CFRelease(newbackup
);
835 CFReleaseSafe(passcode
);
839 CFReleaseSafe(oldbackup
);
842 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
846 case sec_keychain_restore_syncable_id
:
848 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
850 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
852 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
854 CFDataRef passcode
= NULL
;
855 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
856 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
857 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
858 CFReleaseSafe(passcode
);
865 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
869 case sec_item_backup_copy_names_id
:
871 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
872 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
873 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
874 CFReleaseSafe(names
);
876 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
880 case sec_item_backup_handoff_fd_id
:
882 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
883 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
886 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
887 CFRelease(backupName
);
889 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
893 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
897 case sec_item_backup_set_confirmed_manifest_id
:
899 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
900 CFDataRef keybagDigest
= NULL
;
901 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
902 CFDataRef manifest
= NULL
;
903 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
904 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
906 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
907 CFRelease(backupName
);
908 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
910 CFReleaseSafe(manifest
);
912 CFReleaseNull(keybagDigest
);
915 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
919 case sec_item_backup_restore_id
:
921 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
923 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
925 CFStringRef peerID
= NULL
;
926 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
927 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
929 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
931 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
933 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
940 CFReleaseSafe(peerID
);
942 CFRelease(backupName
);
944 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
946 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
950 case sec_ota_pki_asset_version_id
:
952 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
953 SecOTAPKIGetCurrentAssetVersion(&error
));
956 case sec_add_shared_web_credential_id
:
958 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
960 CFTypeRef result
= NULL
;
961 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
962 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
963 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
966 CFReleaseSafe(appID
);
971 case sec_copy_shared_web_credential_id
:
973 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
975 CFTypeRef result
= NULL
;
976 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
977 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
978 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
981 CFReleaseSafe(appID
);
986 case sec_get_log_settings_id
:
988 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
990 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
992 CFReleaseSafe(currentList
);
995 case sec_set_xpc_log_settings_id
:
997 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
999 SecSetXPCLogSettings_Server(newSettings
, &error
);
1001 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1002 CFReleaseNull(newSettings
);
1005 case sec_set_circle_log_settings_id
:
1007 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
1009 SecSetCircleLogSettings_Server(newSettings
, &error
);
1011 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1012 CFReleaseNull(newSettings
);
1015 case sec_otr_session_create_remote_id
:
1017 CFDataRef publicPeerId
= NULL
;
1018 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
1019 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
1021 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
1022 CFRelease(otrSession
);
1024 CFReleaseSafe(publicPeerId
);
1028 case sec_otr_session_process_packet_remote_id
:
1030 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
1031 bool readyForMessages
= false;
1032 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
1033 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
1034 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
1036 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
1037 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
1038 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
1039 CFRelease(outputSessionData
);
1040 CFRelease(outputPacket
);
1042 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1044 CFReleaseSafe(inputPacket
);
1046 CFReleaseSafe(sessionData
);
1050 case kSecXPCOpTryUserCredentials
:
1051 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1052 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1053 SOSCCTryUserCredentials_Server(label
, password
, &error
));
1056 case kSecXPCOpSetUserCredentials
:
1057 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
1058 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1059 SOSCCSetUserCredentials_Server(label
, password
, &error
));
1062 case kSecXPCOpSetUserCredentialsAndDSID
:
1063 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
1064 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1065 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
1069 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
1070 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1071 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
1074 case kSecXPCOpViewSet
:
1076 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
1077 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
1078 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
1079 CFReleaseNull(enabledViews
);
1080 CFReleaseNull(disabledViews
);
1083 case kSecXPCOpSecurityProperty
:
1084 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
1085 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1086 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
1089 case kSecXPCOpCanAuthenticate
:
1090 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1091 SOSCCCanAuthenticate_Server(&error
));
1093 case kSecXPCOpPurgeUserCredentials
:
1094 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1095 SOSCCPurgeUserCredentials_Server(&error
));
1097 case kSecXPCOpDeviceInCircle
:
1098 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1099 SOSCCThisDeviceIsInCircle_Server(&error
));
1101 case kSecXPCOpRequestToJoin
:
1102 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1103 SOSCCRequestToJoinCircle_Server(&error
));
1105 case kSecXPCOpRequestToJoinAfterRestore
:
1106 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1107 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
1109 case kSecXPCOpRequestEnsureFreshParameters
:
1110 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1111 SOSCCRequestEnsureFreshParameters_Server(&error
));
1113 case kSecXPCOpGetAllTheRings
:
1115 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
1116 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
1117 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1118 xpc_release(xpc_dictionary
);
1121 case kSecXPCOpApplyToARing
:
1123 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1124 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
1125 CFReleaseNull(ringName
);
1128 case kSecXPCOpWithdrawlFromARing
:
1130 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1131 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
1132 CFReleaseNull(ringName
);
1135 case kSecXPCOpRingStatus
:
1137 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1138 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
1139 CFReleaseNull(ringName
);
1142 case kSecXPCOpEnableRing
:
1144 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
1145 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
1146 CFReleaseNull(ringName
);
1149 case kSecXPCOpRequestDeviceID
:
1151 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
1153 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
1155 CFReleaseNull(deviceID
);
1158 case kSecXPCOpSetDeviceID
:
1160 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1161 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
1165 case kSecXPCOpHandleIDSMessage
:
1167 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
1168 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
1173 case kSecXPCOpSendIDSMessage
:
1175 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1176 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
1177 CFReleaseNull(message
);
1180 case kSecXPCOpPingTest
:
1182 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1183 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1184 CFReleaseNull(message
);
1187 case kSecXPCOpIDSDeviceID
:
1189 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1192 case kSecXPCOpAccountSetToNew
:
1193 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1195 case kSecXPCOpResetToOffering
:
1196 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1197 SOSCCResetToOffering_Server(&error
));
1199 case kSecXPCOpResetToEmpty
:
1200 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1201 SOSCCResetToEmpty_Server(&error
));
1203 case kSecXPCOpRemoveThisDeviceFromCircle
:
1204 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1205 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1207 case kSecXPCOpRemovePeersFromCircle
:
1209 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfos
, &error
);
1210 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1211 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1212 CFReleaseNull(applicants
);
1215 case kSecXPCOpLoggedOutOfAccount
:
1216 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1217 SOSCCLoggedOutOfAccount_Server(&error
));
1219 case kSecXPCOpBailFromCircle
:
1221 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1222 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1223 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1226 case kSecXPCOpAcceptApplicants
:
1228 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1229 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1230 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1231 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1232 CFReleaseSafe(applicants
);
1235 case kSecXPCOpRejectApplicants
:
1237 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
1238 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1239 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1240 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1241 CFReleaseSafe(applicants
);
1244 case kSecXPCOpSetNewPublicBackupKey
:
1246 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
1247 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1248 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1249 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1250 CFReleaseNull(peerInfo
);
1252 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1253 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1254 xpc_release(xpc_object
);
1256 CFReleaseNull(peerInfoData
);
1257 CFReleaseSafe(publicBackupKey
);
1260 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
1264 case kSecXPCOpSetBagForAllSlices
:
1266 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementRestoreKeychain
)) {
1267 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1268 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1269 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1270 CFReleaseSafe(backupSlice
);
1272 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementRestoreKeychain
, &error
);
1276 case kSecXPCOpCopyApplicantPeerInfo
:
1277 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1278 SOSCCCopyApplicantPeerInfo_Server(&error
),
1281 case kSecXPCOpCopyValidPeerPeerInfo
:
1282 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1283 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1286 case kSecXPCOpValidateUserPublic
:
1288 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1289 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1292 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1293 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1294 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1297 case kSecXPCOpCopyGenerationPeerInfo
:
1298 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1299 SOSCCCopyGenerationPeerInfo_Server(&error
));
1301 case kSecXPCOpCopyRetirementPeerInfo
:
1302 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1303 SOSCCCopyRetirementPeerInfo_Server(&error
),
1306 case kSecXPCOpCopyViewUnawarePeerInfo
:
1307 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1308 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1311 case kSecXPCOpCopyAccountData
:
1313 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1314 xpc_object_t xpc_account_object
= NULL
;
1315 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1317 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1319 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1320 CFReleaseNull(accountData
);
1323 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1327 case kSecXPCOpDeleteAccountData
:
1329 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1330 bool status
= SOSCCDeleteAccountState_Server(&error
);
1331 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1334 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1339 case kSecXPCOpCopyEngineData
:
1341 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1343 xpc_object_t xpc_engine_object
= NULL
;
1344 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1346 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1348 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1349 CFReleaseNull(engineData
);
1353 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1357 case kSecXPCOpDeleteEngineData
:
1359 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1361 bool status
= SOSCCDeleteEngineState_Server(&error
);
1362 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1365 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1369 case kSecXPCOpCopyEngineState
:
1371 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementKeychainCloudCircle
)) {
1373 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1375 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1376 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1377 xpc_release(xpc_array
);
1379 CFReleaseNull(array
);
1382 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementKeychainCloudCircle
, &error
);
1386 case kSecXPCOpCopyPeerPeerInfo
:
1387 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1388 SOSCCCopyPeerPeerInfo_Server(&error
),
1391 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1392 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1393 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1396 case kSecXPCOpCopyMyPeerInfo
:
1398 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1399 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1400 CFReleaseNull(peerInfo
);
1402 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1403 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1404 xpc_release(xpc_object
);
1406 CFReleaseNull(peerInfoData
);
1409 case kSecXPCOpGetLastDepartureReason
:
1410 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1411 SOSCCGetLastDepartureReason_Server(&error
));
1413 case kSecXPCOpSetLastDepartureReason
:
1415 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1416 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1417 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1420 case kSecXPCOpProcessSyncWithAllPeers
:
1421 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1422 SOSCCProcessSyncWithAllPeers_Server(&error
));
1424 case soscc_EnsurePeerRegistration_id
:
1425 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1426 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1428 case kSecXPCOpCopyIncompatibilityInfo
:
1430 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1431 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1435 case kSecXPCOpOTAGetEscrowCertificates
:
1437 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
1438 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
1440 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1441 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1442 xpc_release(xpc_array
);
1444 CFReleaseNull(array
);
1447 case kSecXPCOpOTAPKIGetNewAsset
:
1448 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1449 SecOTAPKISignalNewAsset(&error
));
1451 case kSecXPCOpRollKeys
:
1453 bool force
= xpc_dictionary_get_bool(event
, "force");
1454 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1455 _SecServerRollKeys(force
, &client
, &error
));
1458 case kSecXPCOpSetHSA2AutoAcceptInfo
:
1460 CFDataRef cfbytes
= NULL
;
1461 const uint8_t *bytes
= NULL
;
1464 bytes
= xpc_dictionary_get_data(event
,
1465 kSecXPCKeyHSA2AutoAcceptInfo
, &len
);
1467 SOSCreateError(kSOSErrorBadKey
,
1468 CFSTR("missing autoaccept info"), NULL
, &error
);
1472 cfbytes
= CFDataCreate(NULL
, bytes
, len
);
1474 SOSCreateError(kSOSErrorAllocationFailure
,
1475 CFSTR("could not allocate autoaccept info"),
1480 xpc_dictionary_set_bool(replyMessage
,
1482 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes
, &error
));
1486 case kSecXPCOpWaitForInitialSync
:
1487 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1488 SOSCCWaitForInitialSync_Server(&error
));
1491 case kSecXPCOpCopyYetToSyncViews
:
1493 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1495 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1496 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1497 xpc_release(xpc_array
);
1499 CFReleaseNull(array
);
1502 case kSecXPCOpSetEscrowRecord
:
1504 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1505 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1507 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1509 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1511 CFReleaseNull(escrow_label
);
1514 case kSecXPCOpGetEscrowRecord
:
1516 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1518 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1519 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1520 xpc_release(xpc_dictionary
);
1522 CFReleaseNull(record
);
1525 case kSecXPCOpCheckPeerAvailability
:
1527 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1530 case kSecXPCOpWhoAmI
:
1533 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1534 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1535 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1536 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1537 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1540 case kSecXPCOpTransmogrifyToSyncBubble
:
1542 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainSyncBubble
)) {
1544 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1545 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1547 if (uid
&& services
) {
1548 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1550 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1551 CFReleaseNull(services
);
1553 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1557 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
);
1561 case kSecXPCOpTransmogrifyToSystemKeychain
:
1563 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
)) {
1565 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1566 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1568 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1572 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
);
1576 case kSecXPCOpDeleteUserView
:
1578 if (SecTaskGetBooleanValueForEntitlement(client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
)) {
1581 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1583 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1586 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1589 EntitlementMissing(((enum SecXPCOperation
)operation
), client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
);
1593 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1595 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1597 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1599 CFDataRef ciphertext
= NULL
;
1600 CFDataRef bskbEncoded
= NULL
;
1602 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1603 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1606 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, NULL
, 0);
1607 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, NULL
, 0);
1608 } else if(!result
) {
1609 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, NULL
, 0);
1610 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, NULL
, 0);
1613 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1616 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1620 CFReleaseSafe(plaintext
);
1622 CFReleaseNull(viewname
);
1633 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1634 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1635 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1636 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1638 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1640 xpcError
= SecCreateXPCObjectWithCFError(error
);
1642 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1644 } else if (replyMessage
) {
1645 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1648 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1649 secerror("%@: returning error: %@", client
.task
, error
);
1650 xpcError
= SecCreateXPCObjectWithCFError(error
);
1651 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1655 xpc_connection_send_message(connection
, replyMessage
);
1656 xpc_release(replyMessage
);
1659 xpc_release(xpcError
);
1660 pthread_setspecific(taskThreadKey
, NULL
);
1661 CFReleaseSafe(error
);
1662 CFReleaseSafe(client
.accessGroups
);
1663 CFReleaseSafe(client
.musr
);
1664 CFReleaseSafe(client
.task
);
1665 CFReleaseSafe(domains
);
1666 CFReleaseSafe(clientAuditToken
);
1669 static void securityd_xpc_init(const char *service_name
)
1671 pthread_key_create(&taskThreadKey
, NULL
);
1672 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1674 secdebug("serverxpc", "start");
1675 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1677 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1681 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1682 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1683 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1684 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1685 xpc_retain(connection
);
1687 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1688 securityd_xpc_dictionary_handler(connection
, event
);
1690 xpc_release(connection
);
1694 xpc_connection_resume(connection
);
1697 xpc_connection_resume(listener
);
1701 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1703 #if TARGET_OS_EMBEDDED
1704 static void securityd_soscc_lock_hack() {
1705 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1708 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1709 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1710 // this code will need to be generalized / migrated away from just this specific purpose.
1711 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1712 char *event_description
= xpc_copy_description(object
);
1713 secnotice("events", "%s", event_description
);
1714 free(event_description
);
1717 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1718 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1719 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1720 CFErrorRef error
= NULL
;
1722 uint64_t one_minute
= 60ull;
1723 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1724 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1725 xpc_transaction_begin();
1727 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1728 CFErrorRef localError
= NULL
;
1729 if(!SecAKSUnLockUserKeybag(&localError
))
1730 secerror("failed to unlock: %@", localError
);
1731 CFReleaseNull(localError
);
1732 xpc_transaction_end();
1735 secerror("Failed to take device lock assertion: %@", error
);
1737 CFReleaseSafe(error
);
1738 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1743 int main(int argc
, char *argv
[])
1745 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1746 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1747 seccritical("SIGSTOPing self, awaiting debugger");
1748 kill(getpid(), SIGSTOP
);
1749 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
1750 "Again, for good luck (or bad debuggers)");
1751 kill(getpid(), SIGSTOP
);
1754 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
1756 CFDictionaryRef deviceMode
= MKBUserTypeDeviceMode(NULL
, NULL
);
1757 CFTypeRef value
= NULL
;
1759 if (deviceMode
&& CFDictionaryGetValueIfPresent(deviceMode
, kMKBDeviceModeKey
, &value
) && CFEqual(value
, kMKBDeviceModeMultiUser
)) {
1762 CFReleaseNull(deviceMode
);
1767 const char *serviceName
= kSecuritydXPCServiceName
;
1769 serviceName
= kTrustdXPCServiceName
;
1770 if (argc
> 1 && (!strcmp(argv
[1], "--agent"))) {
1771 serviceName
= kTrustdAgentXPCServiceName
;
1774 securityd_init_server();
1775 securityd_xpc_init(serviceName
);
1778 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1779 #if TARGET_OS_EMBEDDED
1780 securityd_soscc_lock_hack();
1788 /* vi:set ts=4 sw=4 et: */