2 * Copyright (c) 2007-2013 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 <mach/mach.h>
25 #include <mach/message.h>
28 #include <sys/queue.h>
30 #include <Security/SecInternal.h>
31 #include <Security/SecBasePriv.h>
32 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
33 #include <Security/SecCertificatePriv.h>
34 #include <Security/SecPolicyInternal.h>
35 #include <CoreFoundation/CoreFoundation.h>
39 #include <bsm/libbsm.h>
40 #include <utilities/SecIOFormat.h>
41 #include <utilities/debugging.h>
43 #include "securityd_client.h"
45 #include <securityd/SecItemServer.h>
46 #include <securityd/SecTrustServer.h>
47 #include <securityd/SecTrustStoreServer.h>
48 #include <securityd/spi.h>
49 #include <Security/SecTask.h>
51 #include <utilities/SecCFWrappers.h>
52 #include <utilities/SecCFError.h>
53 #include <utilities/SecXPCError.h>
55 // TODO: Make this include work on both platforms.
56 #if TARGET_OS_EMBEDDED
57 #include <Security/SecEntitlements.h>
59 #define kSecEntitlementKeychainSyncUpdates CFSTR("keychain-sync-updates")
60 #define kSecEntitlementKeychainCloudCircle CFSTR("keychain-cloud-circle")
61 /* defines from <Security/SecTask.h> */
62 /* defines from <Security/SecEntitlements.h> */
63 #if TARGET_OS_EMBEDDED
64 #define kSecEntitlementApplicationIdentifier CFSTR("application-identifier")
66 #define kSecEntitlementApplicationIdentifier CFSTR("com.apple.application-identifier")
68 #define kSecEntitlementGetTaskAllow CFSTR("get-task-allow")
69 #define kSecEntitlementKeychainAccessGroups CFSTR("keychain-access-groups")
70 #define kSecEntitlementModifyAnchorCertificates CFSTR("modify-anchor-certificates")
71 #define kSecEntitlementDebugApplications CFSTR("com.apple.springboard.debugapplications")
72 #define kSecEntitlementOpenSensitiveURL CFSTR("com.apple.springboard.opensensitiveurl")
73 #define kSecEntitlementWipeDevice CFSTR("com.apple.springboard.wipedevice")
74 #define kSecEntitlementRemoteNotificationConfigure CFSTR("com.apple.remotenotification.configure")
75 #define kSecEntitlementMigrateKeychain CFSTR("migrate-keychain")
76 #define kSecEntitlementRestoreKeychain CFSTR("restore-keychain")
77 #define kSecEntitlementSyncKeychain CFSTR("sync-keychain")
80 #include <Security/SecuritydXPC.h>
82 #include <libkern/OSAtomic.h>
84 #include <CoreFoundation/CFXPCBridge.h>
87 #include <xpc/private.h>
88 #include <xpc/connection_private.h>
89 #include <AssertMacros.h>
90 #include <SecureObjectSync/SOSCloudCircle.h>
92 #include <securityd/SOSCloudCircleServer.h>
93 #include <SecureObjectSync/SOSCloudCircleInternal.h>
94 #include <sys/sysctl.h>
97 #include <utilities/SecDb.h>
99 #include <securityd/OTATrustUtilities.h>
102 #if TARGET_IPHONE_SIMULATOR
103 #define CHECK_ENTITLEMENTS 0
105 #define CHECK_ENTITLEMENTS 1
108 #if CHECK_ENTITLEMENTS
109 static CFStringRef
SecTaskCopyStringForEntitlement(SecTaskRef task
,
110 CFStringRef entitlement
)
112 CFStringRef value
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
114 if (value
&& CFGetTypeID(value
) != CFStringGetTypeID()) {
122 static CFArrayRef
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
,
123 CFStringRef entitlement
)
125 CFArrayRef value
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
,
128 if (CFGetTypeID(value
) == CFArrayGetTypeID()) {
129 CFIndex ix
, count
= CFArrayGetCount(value
);
130 for (ix
= 0; ix
< count
; ++ix
) {
131 CFStringRef string
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
);
132 if (CFGetTypeID(string
) != CFStringGetTypeID()) {
147 #endif /* CHECK_ENTITLEMENTS */
149 static CFArrayRef
SecTaskCopyAccessGroups(SecTaskRef task
) {
150 #if CHECK_ENTITLEMENTS
151 CFStringRef appID
= SecTaskCopyStringForEntitlement(task
,
152 kSecEntitlementApplicationIdentifier
);
153 CFArrayRef groups
= SecTaskCopyArrayOfStringsForEntitlement(task
,
154 kSecEntitlementKeychainAccessGroups
);
157 CFMutableArrayRef nGroups
= CFArrayCreateMutableCopy(
158 CFGetAllocator(groups
), CFArrayGetCount(groups
) + 1, groups
);
159 CFArrayAppendValue(nGroups
, appID
);
163 groups
= CFArrayCreate(CFGetAllocator(task
),
164 (const void **)&appID
, 1, &kCFTypeArrayCallBacks
);
169 CFArrayRef groups
= SecAccessGroupsGetCurrent();
176 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
,
177 CFStringRef entitlement
) {
178 #if CHECK_ENTITLEMENTS
179 CFStringRef canModify
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
,
183 CFTypeID canModifyType
= CFGetTypeID(canModify
);
184 bool ok
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
);
185 CFRelease(canModify
);
189 #endif /* !CHECK_ENTITLEMENTS */
192 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
193 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
195 size_t password_length
= 0;
196 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
198 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
199 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
201 action(user_label
, user_password
);
203 CFReleaseNull(user_password
);
204 CFReleaseNull(user_label
);
207 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef
*error
) {
210 xpc_object_t xpc_chain
= SecCertificatePathCopyXPCArray(path
, error
);
214 xpc_dictionary_set_value(message
, key
, xpc_chain
);
215 xpc_release(xpc_chain
);
219 static SecCertificateRef
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
221 const void *bytes
= xpc_dictionary_get_data(message
, key
, &length
);
223 SecCertificateRef certificate
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
);
226 SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
);
228 SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
);
233 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
234 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
235 if (!xpc_certificates
)
236 return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
);
237 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
238 return *certificates
;
241 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*certificates
, CFErrorRef
*error
) {
242 xpc_object_t xpc_certificates
= xpc_dictionary_get_value(message
, key
);
243 if (!xpc_certificates
) {
244 *certificates
= NULL
;
247 *certificates
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
);
248 return *certificates
;
251 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef
*policies
, CFErrorRef
*error
) {
252 xpc_object_t xpc_policies
= xpc_dictionary_get_value(message
, key
);
258 *policies
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
);
259 return *policies
!= NULL
;
262 static SecTrustStoreRef
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
263 SecTrustStoreRef ts
= NULL
;
264 CFStringRef domain
= SecXPCDictionaryCopyString(message
, key
, error
);
266 ts
= SecTrustStoreForDomainName(domain
, error
);
272 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef
*error
) {
273 *pvalue
= xpc_dictionary_get_double(message
, key
);
274 if (*pvalue
== NAN
) {
275 return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
);
280 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
281 xpc_type_t type
= xpc_get_type(event
);
282 __block CFErrorRef error
= NULL
;
283 xpc_object_t xpcError
= NULL
;
284 xpc_object_t replyMessage
= NULL
;
285 SecTaskRef clientTask
= NULL
;
286 CFArrayRef accessGroups
= NULL
;
288 secdebug("serverxpc", "entering");
289 if (type
== XPC_TYPE_DICTIONARY
) {
290 // TODO: Find out what we're dispatching.
291 replyMessage
= xpc_dictionary_create_reply(event
);
293 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
294 secdebug("serverxpc", "operation: %@ (%" PRIu64
")", SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
297 #if 1 // CHECK_ENTITLEMENTS
298 audit_token_t auditToken
= {};
299 xpc_connection_get_audit_token(connection
, &auditToken
);
300 clientTask
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
);
301 accessGroups
= SecTaskCopyAccessGroups(clientTask
);
303 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
304 hasEntitlement
= (operation
< kSecXPCOpTryUserCredentials
) ||
305 (clientTask
&& SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementKeychainCloudCircle
));
308 hasEntitlement
= true;
311 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
312 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
314 if (!hasEntitlement
) {
315 CFErrorRef entitlementError
= NULL
;
316 SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementKeychainCloudCircle
);
317 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
);
318 CFReleaseSafe(entitlementError
);
324 case sec_item_add_id
:
326 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
328 CFTypeRef result
= NULL
;
329 if (_SecItemAdd(query
, accessGroups
, &result
, &error
) && result
) {
330 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
337 case sec_item_copy_matching_id
:
339 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
341 CFTypeRef result
= NULL
;
342 if (_SecItemCopyMatching(query
, accessGroups
, &result
, &error
) && result
) {
343 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
350 case sec_item_update_id
:
352 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
354 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
355 if (attributesToUpdate
) {
356 bool result
= _SecItemUpdate(query
, attributesToUpdate
, accessGroups
, &error
);
357 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
358 CFRelease(attributesToUpdate
);
364 case sec_item_delete_id
:
366 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
368 bool result
= _SecItemDelete(query
, accessGroups
, &error
);
369 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
374 case sec_trust_store_contains_id
:
376 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
378 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
381 if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
))
382 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
);
388 case sec_trust_store_set_trust_settings_id
:
390 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
392 SecCertificateRef certificate
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
);
394 CFTypeRef trustSettingsDictOrArray
= NULL
;
395 if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) {
396 bool result
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
);
397 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
398 CFReleaseSafe(trustSettingsDictOrArray
);
400 CFRelease(certificate
);
405 case sec_trust_store_remove_certificate_id
:
407 SecTrustStoreRef ts
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
);
409 CFDataRef digest
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
);
411 bool result
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
);
412 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
418 case sec_delete_all_id
:
419 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
421 case sec_trust_evaluate_id
:
423 CFArrayRef certificates
= NULL
, anchors
= NULL
, policies
= NULL
;
424 bool anchorsOnly
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
);
426 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) &&
427 SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) &&
428 SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) &&
429 SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) {
430 // If we have no error yet, capture connection and reply in block and properly retain them.
431 xpc_retain(connection
);
432 CFRetainSafe(clientTask
);
434 // Clear replyMessage so we don't send a synchronous reply.
435 xpc_object_t asyncReply
= replyMessage
;
438 SecTrustServerEvaluateBlock(certificates
, anchors
, anchorsOnly
, policies
, verifyTime
, accessGroups
, ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) {
439 // Send back reply now
441 CFRetain(replyError
);
443 xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
);
444 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) &&
445 SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) &&
446 SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
);
449 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
);
450 xpc_object_t xpcReplyError
= SecCreateXPCObjectWithCFError(replyError
);
452 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
);
453 xpc_release(xpcReplyError
);
455 CFRelease(replyError
);
457 secdebug("ipc", "%@ %@ reponding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
);
460 xpc_connection_send_message(connection
, asyncReply
);
461 xpc_release(asyncReply
);
462 xpc_release(connection
);
463 CFReleaseSafe(clientTask
);
466 CFReleaseSafe(policies
);
467 CFReleaseSafe(anchors
);
468 CFReleaseSafe(certificates
);
471 case sec_keychain_backup_id
:
473 CFDataRef keybag
= NULL
, passcode
= NULL
;
474 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
475 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
476 CFDataRef backup
= _SecServerKeychainBackup(keybag
, passcode
, &error
);
478 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
481 CFReleaseSafe(passcode
);
483 CFReleaseSafe(keybag
);
487 case sec_keychain_restore_id
:
489 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
491 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
493 CFDataRef passcode
= NULL
;
494 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
495 bool result
= _SecServerKeychainRestore(backup
, keybag
, passcode
, &error
);
496 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
497 CFReleaseSafe(passcode
);
505 case sec_keychain_sync_update_id
:
507 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
509 bool result
= _SecServerKeychainSyncUpdate(updates
, &error
);
510 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
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
:
555 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
556 SecOTAPKIGetCurrentAssetVersion(&error
));
558 case kSecXPCOpTryUserCredentials
:
559 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
560 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
561 SOSCCTryUserCredentials_Server(label
, password
, &error
));
564 case kSecXPCOpSetUserCredentials
:
565 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
566 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
567 SOSCCSetUserCredentials_Server(label
, password
, &error
));
570 case kSecXPCOpCanAuthenticate
:
571 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
572 SOSCCCanAuthenticate_Server(&error
));
574 case kSecXPCOpPurgeUserCredentials
:
575 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
576 SOSCCPurgeUserCredentials_Server(&error
));
578 case kSecXPCOpDeviceInCircle
:
579 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
580 SOSCCThisDeviceIsInCircle_Server(&error
));
582 case kSecXPCOpRequestToJoin
:
583 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
584 SOSCCRequestToJoinCircle_Server(&error
));
586 case kSecXPCOpRequestToJoinAfterRestore
:
587 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
588 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
590 case kSecXPCOpResetToOffering
:
591 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
592 SOSCCResetToOffering_Server(&error
));
594 case kSecXPCOpResetToEmpty
:
595 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
596 SOSCCResetToEmpty_Server(&error
));
598 case kSecXPCOpRemoveThisDeviceFromCircle
:
599 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
600 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
602 case kSecXPCOpBailFromCircle
:
604 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
605 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
606 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
609 case kSecXPCOpAcceptApplicants
:
611 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
612 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
613 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
614 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
615 CFReleaseSafe(applicants
);
618 case kSecXPCOpRejectApplicants
:
620 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
);
621 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
622 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
623 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
624 CFReleaseSafe(applicants
);
627 case kSecXPCOpCopyApplicantPeerInfo
:
629 CFArrayRef array
= SOSCCCopyApplicantPeerInfo_Server(&error
);
631 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
632 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
633 xpc_release(xpc_array
);
635 CFReleaseNull(array
);
638 case kSecXPCOpCopyPeerPeerInfo
:
640 CFArrayRef array
= SOSCCCopyPeerPeerInfo_Server(&error
);
642 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
643 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
644 xpc_release(xpc_array
);
646 CFReleaseNull(array
);
649 case kSecXPCOpCopyConcurringPeerPeerInfo
:
651 CFArrayRef array
= SOSCCCopyConcurringPeerPeerInfo_Server(&error
);
653 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
);
654 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
655 xpc_release(xpc_array
);
657 CFReleaseNull(array
);
660 case kSecXPCOpGetLastDepartureReason
:
661 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
662 SOSCCGetLastDepartureReason_Server(&error
));
664 case kSecXPCOpProcessSyncWithAllPeers
:
665 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
666 SOSCCProcessSyncWithAllPeers_Server(&error
));
668 case kSecXPCOpCopyIncompatibilityInfo
:
669 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
670 SOSCCCopyIncompatibilityInfo_Server(&error
));
672 case kSecXPCOpOTAGetEscrowCertificates
:
674 CFArrayRef array
= SecOTAPKICopyCurrentEscrowCertificates(&error
);
676 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
677 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
678 xpc_release(xpc_array
);
680 CFReleaseNull(array
);
683 case kSecXPCOpOTAPKIGetNewAsset
:
684 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
685 SecOTAPKISignalNewAsset(&error
));
694 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
)
695 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
697 secerror("%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
699 xpcError
= SecCreateXPCObjectWithCFError(error
);
700 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
701 } else if (replyMessage
) {
702 secdebug("ipc", "%@ %@ reponding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
705 SecCFCreateErrorWithFormatAndArguments(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
706 secerror("%@: returning error: %@", clientTask
, error
);
707 xpcError
= SecCreateXPCObjectWithCFError(error
);
708 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
712 xpc_connection_send_message(connection
, replyMessage
);
713 xpc_release(replyMessage
);
716 xpc_release(xpcError
);
717 CFReleaseSafe(error
);
718 CFReleaseSafe(accessGroups
);
719 CFReleaseSafe(clientTask
);
722 static void securityd_xpc_init()
724 secdebug("serverxpc", "start");
726 xpc_track_activity();
727 xpc_connection_t listener
= xpc_connection_create_mach_service(kSecuritydXPCServiceName
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
729 seccritical("security failed to register xpc listener, exiting");
733 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
734 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
735 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
736 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
737 xpc_retain(connection
);
739 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
740 securityd_xpc_dictionary_handler(connection
, event
);
742 xpc_release(connection
);
746 xpc_connection_resume(connection
);
749 xpc_connection_resume(listener
);
752 int main(int argc
, char *argv
[])
754 char *wait4debugger
= getenv("WAIT4DEBUGGER");
755 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
756 seccritical("SIGSTOPing self, awaiting debugger");
757 kill(getpid(), SIGSTOP
);
758 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
,
759 "Again, for good luck (or bad debuggers)");
760 kill(getpid(), SIGSTOP
);
763 securityd_init_server();
764 securityd_xpc_init();
769 /* vi:set ts=4 sw=4 et: */