2 * Copyright (c) 2007-2014 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 <SecureObjectSync/SOSCloudCircle.h>
25 #include <SecureObjectSync/SOSCloudCircleInternal.h>
26 #include <SecureObjectSync/SOSInternal.h>
27 #include <SecureObjectSync/SOSPeerInfoCollections.h>
28 #include <Security/SecBasePriv.h>
29 #include <Security/SecCertificatePriv.h>
30 #include <Security/SecEntitlements.h>
31 #include <Security/SecInternal.h>
32 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
33 #include <Security/SecPolicyInternal.h>
34 #include <Security/SecTask.h>
35 #include <Security/SecuritydXPC.h>
36 #include <securityd/OTATrustUtilities.h>
37 #include <securityd/SOSCloudCircleServer.h>
38 #include <securityd/SecItemServer.h>
39 #include <securityd/SecLogSettingsServer.h>
40 #include <securityd/SecOTRRemote.h>
41 #include <securityd/SecTrustServer.h>
42 #include <securityd/SecTrustStoreServer.h>
43 #include <securityd/iCloudTrace.h>
44 #include <securityd/spi.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/SecCFWrappers.h>
47 #include <utilities/SecDb.h>
48 #include <utilities/SecIOFormat.h>
49 #include <utilities/SecXPCError.h>
50 #include <utilities/debugging.h>
52 #include <AssertMacros.h>
53 #include <CoreFoundation/CFXPCBridge.h>
54 #include <CoreFoundation/CoreFoundation.h>
56 #include <bsm/libbsm.h>
57 #include <ipc/securityd_client.h>
58 #include <libkern/OSAtomic.h>
59 #include <mach/mach.h>
60 #include <mach/message.h>
62 #include <sys/queue.h>
63 #include <sys/sysctl.h>
65 #include <xpc/private.h>
68 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
69 #include <Security/SecTaskPriv.h>
72 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
73 CFStringRef entitlement
)
75 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
77 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
85 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
86 CFStringRef entitlement
)
88 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
91 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
92 CFIndex ix
, count
= CFArrayGetCount(value
);
93 for (ix
= 0; ix
< count
; ++ix
) {
94 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
95 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
110 static CFStringRef
SecTaskCopyApplicationIdentifier(SecTaskRef task
) {
111 return SecTaskCopyStringForEntitlement(task
,
112 kSecEntitlementApplicationIdentifier
);
115 static CFArrayRef
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) {
116 return SecTaskCopyArrayOfStringsForEntitlement(task
,
117 kSecEntitlementAssociatedDomains
);
120 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
121 CFMutableArrayRef groups
= NULL
;
122 CFArrayRef keychainAccessGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
123 kSecEntitlementKeychainAccessGroups
);
124 CFArrayRef appleSecurityApplicationGroups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
125 kSecEntitlementAppleSecurityApplicationGroups
);
126 CFStringRef appID
= SecTaskCopyApplicationIdentifier(task
);
127 CFIndex kagLen
= keychainAccessGroups
? CFArrayGetCount(keychainAccessGroups
) : 0;
128 CFIndex asagLen
= appleSecurityApplicationGroups
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0;
129 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
130 if ((appID
|| asagLen
) && !SecTaskEntitlementsValidated(task
)) {
131 CFReleaseNull(appID
);
135 CFIndex len
= kagLen
+ asagLen
+ (appID
? 1 : 0);
137 groups
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
);
139 CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
));
141 CFArrayAppendValue(groups
, appID
);
143 CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
));
144 #if TARGET_IPHONE_SIMULATOR
146 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
147 groups
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent());
151 CFReleaseSafe(appID
);
152 CFReleaseSafe(keychainAccessGroups
);
153 CFReleaseSafe(appleSecurityApplicationGroups
);
157 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
158 CFStringRef entitlement
) {
159 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
163 CFTypeID canModifyType
= CFGetTypeID(canModify
);
164 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
165 CFRelease(canModify
);
169 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
170 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
172 size_t password_length
= 0;
173 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
175 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
176 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
178 action(user_label
, user_password
);
180 CFReleaseNull(user_password
);
181 CFReleaseNull(user_label
);
184 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
187 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
191 xpc_dictionary_set_value(message
, key
, xpc_chain
);
192 xpc_release(xpc_chain
);
196 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
198 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
200 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
203 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
205 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
210 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
211 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
212 if (!xpc_certificates
)
213 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
214 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
215 return *certificates
;
218 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
219 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
220 if (!xpc_certificates
) {
221 *certificates
= NULL
;
224 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
225 return *certificates
;
228 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
229 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
235 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
236 return *policies
!= NULL
;
239 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
240 SecTrustStoreRef ts
= NULL
;
241 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
243 ts
= SecTrustStoreForDomainName(domain
, error
);
249 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
250 *pvalue
= xpc_dictionary_get_double(message
, key
);
251 if (*pvalue
== NAN
) {
252 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
257 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
258 xpc_type_t type
= xpc_get_type(event
);
259 __block CFErrorRef error
= NULL
;
260 xpc_object_t xpcError
= NULL
;
261 xpc_object_t replyMessage
= NULL
;
262 SecTaskRef clientTask
= NULL
;
263 CFArrayRef accessGroups
= NULL
;
264 CFArrayRef domains
= NULL
;
266 secdebug("serverxpc", "entering");
267 if (type
== XPC_TYPE_DICTIONARY
) {
268 // TODO: Find out what we're dispatching.
269 replyMessage
= xpc_dictionary_create_reply(event
);
271 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
272 secdebug("serverxpc", "operation: %@ (%" PRIu64
")", SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
275 audit_token_t auditToken
= {};
276 xpc_connection_get_audit_token(connection
, &auditToken
);
278 clientTask
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
279 accessGroups
= SecTaskCopyAccessGroups(clientTask
);
280 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
281 domains
= SecTaskCopySharedWebCredentialDomains(clientTask
);
284 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
285 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
286 (clientTask
&& SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementKeychainCloudCircle
));
288 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
289 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
291 if (!hasEntitlement
) {
292 CFErrorRef entitlementError
= NULL
;
293 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementKeychainCloudCircle
);
294 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
295 CFReleaseSafe(entitlementError
);
301 case sec_item_add_id
:
303 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
305 CFTypeRef result
= NULL
;
306 if (_SecItemAdd(query
, accessGroups
, &result
, &error
) && result
) {
307 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
314 case sec_item_copy_matching_id
:
316 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
318 CFTypeRef result
= NULL
;
319 if (_SecItemCopyMatching(query
, accessGroups
, &result
, &error
) && result
) {
320 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
327 case sec_item_update_id
:
329 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
331 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
332 if (attributesToUpdate
) {
333 bool result
= _SecItemUpdate(query
, attributesToUpdate
, accessGroups
, &error
);
334 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
335 CFRelease(attributesToUpdate
);
341 case sec_item_delete_id
:
343 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
345 bool result
= _SecItemDelete(query
, accessGroups
, &error
);
346 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
351 case sec_trust_store_contains_id
:
353 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
355 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
358 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
359 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
365 case sec_trust_store_set_trust_settings_id
:
367 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
369 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
371 CFTypeRef trustSettingsDictOrArray
= NULL
;
372 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
373 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
374 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
375 CFReleaseSafe(trustSettingsDictOrArray
);
377 CFRelease(certificate
);
382 case sec_trust_store_remove_certificate_id
:
384 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
386 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
388 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
389 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
395 case sec_delete_all_id
:
396 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
398 case sec_trust_evaluate_id
:
400 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
;
401 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
403 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
404 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
405 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
406 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
407 // If we have no error yet, capture connection and reply in block and properly retain them.
408 xpc_retain(connection
);
409 CFRetainSafe(clientTask
);
411 // Clear replyMessage so we don't send a synchronous reply.
412 xpc_object_t asyncReply
= replyMessage
;
415 SecTrustServerEvaluateBlock(certificates
, anchors
, anchorsOnly
, policies
, verifyTime
, accessGroups
, ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
416 // Send back reply now
418 CFRetain(replyError
);
420 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
421 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
422 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
423 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
426 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
427 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
429 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
430 xpc_release(xpcReplyError
);
432 CFRelease(replyError
);
434 secdebug("ipc", "%@ %@ reponding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
437 xpc_connection_send_message(connection
, asyncReply
);
438 xpc_release(asyncReply
);
439 xpc_release(connection
);
440 CFReleaseSafe(clientTask
);
443 CFReleaseSafe(policies
);
444 CFReleaseSafe(anchors
);
445 CFReleaseSafe(certificates
);
448 case sec_keychain_backup_id
:
450 CFDataRef keybag
= NULL
, passcode
= NULL
;
451 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
452 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
453 CFDataRef backup
= _SecServerKeychainBackup(keybag
, passcode
, &error
);
455 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
458 CFReleaseSafe(passcode
);
460 CFReleaseSafe(keybag
);
464 case sec_keychain_restore_id
:
466 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
468 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
470 CFDataRef passcode
= NULL
;
471 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
472 bool result
= _SecServerKeychainRestore(backup
, keybag
, passcode
, &error
);
473 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
474 CFReleaseSafe(passcode
);
482 case sec_keychain_sync_update_key_parameter_id
:
484 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
486 CFArrayRef result
= _SecServerKeychainSyncUpdateKeyParameter(updates
, &error
);
487 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
488 CFReleaseNull(result
);
490 CFReleaseNull(updates
);
493 case sec_keychain_sync_update_circle_id
:
495 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
497 CFArrayRef result
= _SecServerKeychainSyncUpdateCircle(updates
, &error
);
498 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
499 CFReleaseNull(result
);
501 CFReleaseNull(updates
);
504 case sec_keychain_sync_update_message_id
:
506 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
508 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
509 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
510 CFReleaseNull(result
);
512 CFReleaseNull(updates
);
515 case sec_keychain_backup_syncable_id
:
517 CFDictionaryRef oldbackup
= NULL
;
518 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
519 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
521 CFDataRef passcode
= NULL
;
522 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
523 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
525 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
526 CFRelease(newbackup
);
528 CFReleaseSafe(passcode
);
532 CFReleaseSafe(oldbackup
);
536 case sec_keychain_restore_syncable_id
:
538 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
540 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
542 CFDataRef passcode
= NULL
;
543 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
544 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
545 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
546 CFReleaseSafe(passcode
);
554 case sec_ota_pki_asset_version_id
:
556 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
557 SecOTAPKIGetCurrentAssetVersion(&error
));
560 case sec_add_shared_web_credential_id
:
562 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
564 CFTypeRef result
= NULL
;
565 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
566 if (_SecAddSharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
567 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
570 CFReleaseSafe(appID
);
575 case sec_copy_shared_web_credential_id
:
577 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
579 CFTypeRef result
= NULL
;
580 CFStringRef appID
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
;
581 if (_SecCopySharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
582 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
585 CFReleaseSafe(appID
);
590 case sec_get_log_settings_id
:
592 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
594 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
596 CFReleaseSafe(currentList
);
599 case sec_set_xpc_log_settings_id
:
601 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
603 SecSetXPCLogSettings_Server(newSettings
, &error
);
605 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
606 CFReleaseNull(newSettings
);
609 case sec_otr_session_create_remote_id
:
611 CFDataRef publicPeerId
= NULL
;
612 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
613 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
615 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
616 CFRelease(otrSession
);
618 CFReleaseSafe(publicPeerId
);
622 case sec_otr_session_process_packet_remote_id
:
624 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
625 bool readyForMessages
= false;
626 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
627 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
628 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
630 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
631 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
632 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
633 CFRelease(outputSessionData
);
634 CFRelease(outputPacket
);
636 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
638 CFReleaseSafe(inputPacket
);
640 CFReleaseSafe(sessionData
);
644 case kSecXPCOpTryUserCredentials
:
645 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
646 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
647 SOSCCTryUserCredentials_Server(label
, password
, &error
));
650 case kSecXPCOpSetUserCredentials
:
651 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
652 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
653 SOSCCSetUserCredentials_Server(label
, password
, &error
));
656 case kSecXPCOpCanAuthenticate
:
657 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
658 SOSCCCanAuthenticate_Server(&error
));
660 case kSecXPCOpPurgeUserCredentials
:
661 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
662 SOSCCPurgeUserCredentials_Server(&error
));
664 case kSecXPCOpDeviceInCircle
:
665 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
666 SOSCCThisDeviceIsInCircle_Server(&error
));
668 case kSecXPCOpRequestToJoin
:
669 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
670 SOSCCRequestToJoinCircle_Server(&error
));
672 case kSecXPCOpRequestToJoinAfterRestore
:
673 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
674 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
676 case kSecXPCOpRequestEnsureFreshParameters
:
677 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
678 SOSCCRequestEnsureFreshParameters_Server(&error
));
680 case kSecXPCOpRequestDeviceID
:
682 CFStringRef deviceID
= SOSCCRequestDeviceID_Server(&error
);
684 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
688 case kSecXPCOpSetDeviceID
:
690 secerror("securityd_xpc_dictionary_handler!");
691 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
692 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
696 case kSecXPCOpResetToOffering
:
697 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
698 SOSCCResetToOffering_Server(&error
));
700 case kSecXPCOpResetToEmpty
:
701 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
702 SOSCCResetToEmpty_Server(&error
));
704 case kSecXPCOpRemoveThisDeviceFromCircle
:
705 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
706 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
708 case kSecXPCOpBailFromCircle
:
710 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
711 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
712 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
715 case kSecXPCOpAcceptApplicants
:
717 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
718 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
719 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
720 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
721 CFReleaseSafe(applicants
);
724 case kSecXPCOpRejectApplicants
:
726 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
727 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
728 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
729 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
730 CFReleaseSafe(applicants
);
733 case kSecXPCOpCopyApplicantPeerInfo
:
735 CFArrayRef array
= SOSCCCopyApplicantPeerInfo_Server(&error
);
737 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
738 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
739 xpc_release(xpc_array
);
741 CFReleaseNull(array
);
744 case kSecXPCOpCopyValidPeerPeerInfo
:
746 CFArrayRef array
= SOSCCCopyValidPeerPeerInfo_Server(&error
);
748 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
749 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
750 xpc_release(xpc_array
);
752 CFReleaseNull(array
);
755 case kSecXPCOpValidateUserPublic
:
757 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
758 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
761 case kSecXPCOpCopyNotValidPeerPeerInfo
:
763 CFArrayRef array
= SOSCCCopyNotValidPeerPeerInfo_Server(&error
);
765 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
766 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
767 xpc_release(xpc_array
);
769 CFReleaseNull(array
);
772 case kSecXPCOpCopyGenerationPeerInfo
:
774 CFArrayRef array
= SOSCCCopyGenerationPeerInfo_Server(&error
);
776 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
777 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
778 xpc_release(xpc_array
);
780 CFReleaseNull(array
);
783 case kSecXPCOpCopyRetirementPeerInfo
:
785 CFArrayRef array
= SOSCCCopyRetirementPeerInfo_Server(&error
);
787 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
788 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
789 xpc_release(xpc_array
);
791 CFReleaseNull(array
);
794 case kSecXPCOpCopyPeerPeerInfo
:
796 CFArrayRef array
= SOSCCCopyPeerPeerInfo_Server(&error
);
798 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
799 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
800 xpc_release(xpc_array
);
802 CFReleaseNull(array
);
805 case kSecXPCOpCopyConcurringPeerPeerInfo
:
807 CFArrayRef array
= SOSCCCopyConcurringPeerPeerInfo_Server(&error
);
809 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
810 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
811 xpc_release(xpc_array
);
813 CFReleaseNull(array
);
816 case kSecXPCOpGetLastDepartureReason
:
817 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
818 SOSCCGetLastDepartureReason_Server(&error
));
820 case kSecXPCOpProcessSyncWithAllPeers
:
821 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
822 SOSCCProcessSyncWithAllPeers_Server(&error
));
824 case soscc_EnsurePeerRegistration_id
:
825 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
826 SOSCCProcessEnsurePeerRegistration_Server(&error
));
828 case kSecXPCOpCopyIncompatibilityInfo
: {
829 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
830 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
834 case kSecXPCOpOTAGetEscrowCertificates
:
836 uint32_t escrowRootType
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType");
837 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
);
839 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
840 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
841 xpc_release(xpc_array
);
843 CFReleaseNull(array
);
846 case kSecXPCOpOTAPKIGetNewAsset
:
847 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
848 SecOTAPKISignalNewAsset(&error
));
850 case kSecXPCOpRollKeys
:
852 bool force
= xpc_dictionary_get_bool(event
, "force");
853 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
854 _SecServerRollKeys(force
, &error
));
864 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
865 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
867 secerror("%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
869 xpcError
= SecCreateXPCObjectWithCFError(error
);
870 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
871 } else if (replyMessage
) {
872 secdebug("ipc", "%@ %@ responding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
875 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
876 secerror("%@: returning error: %@", clientTask
, error
);
877 xpcError
= SecCreateXPCObjectWithCFError(error
);
878 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
882 xpc_connection_send_message(connection
, replyMessage
);
883 xpc_release(replyMessage
);
886 xpc_release(xpcError
);
887 CFReleaseSafe(error
);
888 CFReleaseSafe(accessGroups
);
889 CFReleaseSafe(domains
);
890 CFReleaseSafe(clientTask
);
893 static void securityd_xpc_init()
895 secdebug("serverxpc", "start");
897 xpc_connection_t listener
= xpc_connection_create_mach_service(kSecuritydXPCServiceName
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
899 seccritical("security failed to register xpc listener, exiting");
903 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
904 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
905 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
906 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
907 xpc_retain(connection
);
909 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
910 securityd_xpc_dictionary_handler(connection
, event
);
912 xpc_release(connection
);
916 xpc_connection_resume(connection
);
919 xpc_connection_resume(listener
);
922 int main(int argc
, char *argv
[])
924 char *wait4debugger
= getenv("WAIT4DEBUGGER");
925 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
926 seccritical("SIGSTOPing self, awaiting debugger");
927 kill(getpid(), SIGSTOP
);
928 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
929 "Again, for good luck (or bad debuggers)");
930 kill(getpid(), SIGSTOP
);
933 securityd_init_server();
934 securityd_xpc_init();
935 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, (NSEC_PER_SEC
* 10)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0),
937 InitializeCloudKeychainTracing();
943 /* vi:set ts=4 sw=4 et: */