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 static CFStringRef 
SecTaskCopyStringForEntitlement(SecTaskRef task
, 
  69     CFStringRef entitlement
) 
  71     CFStringRef value 
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
, 
  73     if (value 
&& CFGetTypeID(value
) != CFStringGetTypeID()) { 
  81 static CFArrayRef 
SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task
, 
  82     CFStringRef entitlement
) 
  84     CFArrayRef value 
= (CFArrayRef
)SecTaskCopyValueForEntitlement(task
, 
  87         if (CFGetTypeID(value
) == CFArrayGetTypeID()) { 
  88             CFIndex ix
, count 
= CFArrayGetCount(value
); 
  89             for (ix 
= 0; ix 
< count
; ++ix
) { 
  90                 CFStringRef string 
= (CFStringRef
)CFArrayGetValueAtIndex(value
, ix
); 
  91                 if (CFGetTypeID(string
) != CFStringGetTypeID()) { 
 106 static CFStringRef 
SecTaskCopyApplicationIdentifier(SecTaskRef task
) { 
 107     return SecTaskCopyStringForEntitlement(task
, 
 108         kSecEntitlementApplicationIdentifier
); 
 111 static CFArrayRef 
SecTaskCopySharedWebCredentialDomains(SecTaskRef task
) { 
 112     return SecTaskCopyArrayOfStringsForEntitlement(task
, 
 113         kSecEntitlementAssociatedDomains
); 
 116 static CFArrayRef 
SecTaskCopyAccessGroups(SecTaskRef task
) { 
 117     CFMutableArrayRef groups 
= NULL
; 
 118     CFArrayRef keychainAccessGroups 
= SecTaskCopyArrayOfStringsForEntitlement(task
, 
 119         kSecEntitlementKeychainAccessGroups
); 
 120     CFArrayRef appleSecurityApplicationGroups 
= SecTaskCopyArrayOfStringsForEntitlement(task
, 
 121         kSecEntitlementAppleSecurityApplicationGroups
); 
 122     CFStringRef appID 
= SecTaskCopyApplicationIdentifier(task
); 
 123     CFIndex kagLen 
= keychainAccessGroups 
? CFArrayGetCount(keychainAccessGroups
) : 0; 
 124     CFIndex asagLen 
= appleSecurityApplicationGroups 
? CFArrayGetCount(appleSecurityApplicationGroups
) : 0; 
 125     CFIndex len 
= kagLen 
+ asagLen 
+ (appID 
? 1 : 0); 
 127         groups 
= CFArrayCreateMutable(kCFAllocatorDefault
, len
, &kCFTypeArrayCallBacks
); 
 129             CFArrayAppendArray(groups
, keychainAccessGroups
, CFRangeMake(0, kagLen
)); 
 131             CFArrayAppendValue(groups
, appID
); 
 133             CFArrayAppendArray(groups
, appleSecurityApplicationGroups
, CFRangeMake(0, asagLen
)); 
 134 #if TARGET_IPHONE_SIMULATOR 
 136         secwarning("No keychain access group specified whilst running in simulator, falling back to default set"); 
 137         groups 
= (CFMutableArrayRef
)CFRetainSafe(SecAccessGroupsGetCurrent()); 
 141     CFReleaseSafe(appID
); 
 142     CFReleaseSafe(keychainAccessGroups
); 
 143     CFReleaseSafe(appleSecurityApplicationGroups
); 
 147 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task
, 
 148     CFStringRef entitlement
) { 
 149     CFStringRef canModify 
= (CFStringRef
)SecTaskCopyValueForEntitlement(task
, 
 153     CFTypeID canModifyType 
= CFGetTypeID(canModify
); 
 154     bool ok 
= (CFBooleanGetTypeID() == canModifyType
) && CFBooleanGetValue((CFBooleanRef
)canModify
); 
 155     CFRelease(canModify
); 
 159 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) { 
 160     const char *label_utf8 
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
); 
 162     size_t password_length 
= 0; 
 163     const void *password_data 
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
); 
 165     CFDataRef user_password 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
); 
 166     CFStringRef user_label 
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
); 
 168     action(user_label
, user_password
); 
 170     CFReleaseNull(user_password
); 
 171     CFReleaseNull(user_label
); 
 174 static bool SecXPCDictionarySetChainOptional(xpc_object_t message
, const char *key
, SecCertificatePathRef path
, CFErrorRef 
*error
) { 
 177     xpc_object_t xpc_chain 
= SecCertificatePathCopyXPCArray(path
, error
); 
 181     xpc_dictionary_set_value(message
, key
, xpc_chain
); 
 182     xpc_release(xpc_chain
); 
 186 static SecCertificateRef 
SecXPCDictionaryCopyCertificate(xpc_object_t message
, const char *key
, CFErrorRef 
*error
) { 
 188     const void *bytes 
= xpc_dictionary_get_data(message
, key
, &length
); 
 190         SecCertificateRef certificate 
= SecCertificateCreateWithBytes(kCFAllocatorDefault
, bytes
, length
); 
 193         SecError(errSecDecode
, error
, CFSTR("object for key %s failed to create certificate from data"), key
); 
 195         SecError(errSecParam
, error
, CFSTR("object for key %s missing"), key
); 
 200 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message
, const char *key
, CFArrayRef 
*certificates
, CFErrorRef 
*error
) { 
 201     xpc_object_t xpc_certificates 
= xpc_dictionary_get_value(message
, key
); 
 202     if (!xpc_certificates
) 
 203         return SecError(errSecAllocate
, error
, CFSTR("no certs for key %s"), key
); 
 204     *certificates 
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
); 
 205     return *certificates
; 
 208 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message
, const char *key
, CFArrayRef 
*certificates
, CFErrorRef 
*error
) { 
 209     xpc_object_t xpc_certificates 
= xpc_dictionary_get_value(message
, key
); 
 210     if (!xpc_certificates
) { 
 211         *certificates 
= NULL
; 
 214     *certificates 
= SecCertificateXPCArrayCopyArray(xpc_certificates
, error
); 
 215     return *certificates
; 
 218 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message
, const char *key
, CFArrayRef 
*policies
, CFErrorRef 
*error
) { 
 219     xpc_object_t xpc_policies 
= xpc_dictionary_get_value(message
, key
); 
 225     *policies 
= SecPolicyXPCArrayCopyArray(xpc_policies
, error
); 
 226     return *policies 
!= NULL
; 
 229 static SecTrustStoreRef 
SecXPCDictionaryGetTrustStore(xpc_object_t message
, const char *key
, CFErrorRef 
*error
) { 
 230     SecTrustStoreRef ts 
= NULL
; 
 231     CFStringRef domain 
= SecXPCDictionaryCopyString(message
, key
, error
); 
 233         ts 
= SecTrustStoreForDomainName(domain
, error
); 
 239 static bool SecXPCDictionaryGetDouble(xpc_object_t message
, const char *key
, double *pvalue
, CFErrorRef 
*error
) { 
 240     *pvalue 
= xpc_dictionary_get_double(message
, key
); 
 241     if (*pvalue 
== NAN
) { 
 242         return SecError(errSecParam
, error
, CFSTR("object for key %s bad double"), key
); 
 247 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) { 
 248         xpc_type_t type 
= xpc_get_type(event
); 
 249     __block CFErrorRef error 
= NULL
; 
 250     xpc_object_t xpcError 
= NULL
; 
 251     xpc_object_t replyMessage 
= NULL
; 
 252     SecTaskRef clientTask 
= NULL
; 
 253     CFArrayRef accessGroups 
= NULL
; 
 254     CFArrayRef domains 
= NULL
; 
 256     secdebug("serverxpc", "entering"); 
 257     if (type 
== XPC_TYPE_DICTIONARY
) { 
 258         // TODO: Find out what we're dispatching. 
 259         replyMessage 
= xpc_dictionary_create_reply(event
); 
 261         uint64_t operation 
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
); 
 262                 secdebug("serverxpc", "operation: %@ (%" PRIu64 
")", SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
); 
 265         audit_token_t auditToken 
= {}; 
 266         xpc_connection_get_audit_token(connection
, &auditToken
); 
 268         clientTask 
= SecTaskCreateWithAuditToken(kCFAllocatorDefault
, auditToken
); 
 269         accessGroups 
= SecTaskCopyAccessGroups(clientTask
); 
 270         if (operation 
== sec_add_shared_web_credential_id 
|| operation 
== sec_copy_shared_web_credential_id
) { 
 271             domains 
= SecTaskCopySharedWebCredentialDomains(clientTask
); 
 274         // operations before kSecXPCOpTryUserCredentials don't need this entitlement. 
 275         hasEntitlement 
= (operation 
< kSecXPCOpTryUserCredentials
) || 
 276         (clientTask 
&& SecTaskGetBooleanValueForEntitlement(clientTask
, kSecEntitlementKeychainCloudCircle
)); 
 278         // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle" 
 279         //  we disable entitlement enforcement. However, we still log so we know who needs the entitlement 
 281         if (!hasEntitlement
) { 
 282             CFErrorRef entitlementError 
= NULL
; 
 283             SecError(errSecMissingEntitlement
, &entitlementError
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), clientTask
, kSecEntitlementKeychainCloudCircle
); 
 284             secnotice("serverxpc", "MissingEntitlement: %@", entitlementError
); 
 285             CFReleaseSafe(entitlementError
); 
 291             case sec_item_add_id
: 
 293                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 295                     CFTypeRef result 
= NULL
; 
 296                     if (_SecItemAdd(query
, accessGroups
, &result
, &error
) && result
) { 
 297                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 304             case sec_item_copy_matching_id
: 
 306                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 308                     CFTypeRef result 
= NULL
; 
 309                     if (_SecItemCopyMatching(query
, accessGroups
, &result
, &error
) && result
) { 
 310                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 317             case sec_item_update_id
: 
 319                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 321                     CFDictionaryRef attributesToUpdate 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
); 
 322                     if (attributesToUpdate
) { 
 323                         bool result 
= _SecItemUpdate(query
, attributesToUpdate
, accessGroups
, &error
); 
 324                         xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 325                         CFRelease(attributesToUpdate
); 
 331             case sec_item_delete_id
: 
 333                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 335                     bool result 
= _SecItemDelete(query
, accessGroups
, &error
); 
 336                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 341             case sec_trust_store_contains_id
: 
 343                 SecTrustStoreRef ts 
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
); 
 345                     CFDataRef digest 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
); 
 348                         if (SecTrustStoreContainsCertificateWithDigest(ts
, digest
, &contains
, &error
)) 
 349                             xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, contains
); 
 355             case sec_trust_store_set_trust_settings_id
: 
 357                 SecTrustStoreRef ts 
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
); 
 359                     SecCertificateRef certificate 
= SecXPCDictionaryCopyCertificate(event
, kSecXPCKeyCertificate
, &error
); 
 361                         CFTypeRef trustSettingsDictOrArray 
= NULL
; 
 362                         if (SecXPCDictionaryCopyPListOptional(event
, kSecXPCKeySettings
, &trustSettingsDictOrArray
, &error
)) { 
 363                             bool result 
= _SecTrustStoreSetTrustSettings(ts
, certificate
, trustSettingsDictOrArray
, &error
); 
 364                             xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 365                             CFReleaseSafe(trustSettingsDictOrArray
); 
 367                         CFRelease(certificate
); 
 372             case sec_trust_store_remove_certificate_id
: 
 374                 SecTrustStoreRef ts 
= SecXPCDictionaryGetTrustStore(event
, kSecXPCKeyDomain
, &error
); 
 376                     CFDataRef digest 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyDigest
, &error
); 
 378                         bool result 
= SecTrustStoreRemoveCertificateWithDigest(ts
, digest
, &error
); 
 379                         xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 385             case sec_delete_all_id
: 
 386                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
)); 
 388             case sec_trust_evaluate_id
: 
 390                 CFArrayRef certificates 
= NULL
, anchors 
= NULL
, policies 
= NULL
; 
 391                 bool anchorsOnly 
= xpc_dictionary_get_bool(event
, kSecTrustAnchorsOnlyKey
); 
 393                 if (SecXPCDictionaryCopyCertificates(event
, kSecTrustCertificatesKey
, &certificates
, &error
) && 
 394                     SecXPCDictionaryCopyCertificatesOptional(event
, kSecTrustAnchorsKey
, &anchors
, &error
) && 
 395                     SecXPCDictionaryCopyPoliciesOptional(event
, kSecTrustPoliciesKey
, &policies
, &error
) && 
 396                     SecXPCDictionaryGetDouble(event
, kSecTrustVerifyDateKey
, &verifyTime
, &error
)) { 
 397                     // If we have no error yet, capture connection and reply in block and properly retain them. 
 398                     xpc_retain(connection
); 
 399                     CFRetainSafe(clientTask
); 
 401                     // Clear replyMessage so we don't send a synchronous reply. 
 402                     xpc_object_t asyncReply 
= replyMessage
; 
 405                     SecTrustServerEvaluateBlock(certificates
, anchors
, anchorsOnly
, policies
, verifyTime
, accessGroups
, ^(SecTrustResultType tr
, CFArrayRef details
, CFDictionaryRef info
, SecCertificatePathRef chain
, CFErrorRef replyError
) { 
 406                         // Send back reply now 
 408                             CFRetain(replyError
); 
 410                             xpc_dictionary_set_int64(asyncReply
, kSecTrustResultKey
, tr
); 
 411                             SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustDetailsKey
, details
, &replyError
) && 
 412                             SecXPCDictionarySetPListOptional(asyncReply
, kSecTrustInfoKey
, info
, &replyError
) && 
 413                             SecXPCDictionarySetChainOptional(asyncReply
, kSecTrustChainKey
, chain
, &replyError
); 
 416                             secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyError
); 
 417                             xpc_object_t xpcReplyError 
= SecCreateXPCObjectWithCFError(replyError
); 
 419                                 xpc_dictionary_set_value(asyncReply
, kSecXPCKeyError
, xpcReplyError
); 
 420                                 xpc_release(xpcReplyError
); 
 422                             CFRelease(replyError
); 
 424                             secdebug("ipc", "%@ %@ reponding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), asyncReply
); 
 427                         xpc_connection_send_message(connection
, asyncReply
); 
 428                         xpc_release(asyncReply
); 
 429                         xpc_release(connection
); 
 430                         CFReleaseSafe(clientTask
); 
 433                 CFReleaseSafe(policies
); 
 434                 CFReleaseSafe(anchors
); 
 435                 CFReleaseSafe(certificates
); 
 438             case sec_keychain_backup_id
: 
 440                 CFDataRef keybag 
= NULL
, passcode 
= NULL
; 
 441                 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) { 
 442                     if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) { 
 443                         CFDataRef backup 
= _SecServerKeychainBackup(keybag
, passcode
, &error
); 
 445                             SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
); 
 448                         CFReleaseSafe(passcode
); 
 450                     CFReleaseSafe(keybag
); 
 454             case sec_keychain_restore_id
: 
 456                     CFDataRef backup 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
); 
 458                         CFDataRef keybag 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
); 
 460                             CFDataRef passcode 
= NULL
; 
 461                             if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) { 
 462                                 bool result 
= _SecServerKeychainRestore(backup
, keybag
, passcode
, &error
); 
 463                                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 464                                 CFReleaseSafe(passcode
); 
 472                 case sec_keychain_sync_update_key_parameter_id
: 
 474                     CFDictionaryRef updates 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 476                         CFArrayRef result 
= _SecServerKeychainSyncUpdateKeyParameter(updates
, &error
); 
 477                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 478                         CFReleaseNull(result
); 
 480                     CFReleaseNull(updates
); 
 483                 case sec_keychain_sync_update_circle_id
: 
 485                     CFDictionaryRef updates 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 487                         CFArrayRef result 
= _SecServerKeychainSyncUpdateCircle(updates
, &error
); 
 488                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 489                         CFReleaseNull(result
); 
 491                     CFReleaseNull(updates
); 
 494                 case sec_keychain_sync_update_message_id
: 
 496                     CFDictionaryRef updates 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 498                         CFArrayRef result 
= _SecServerKeychainSyncUpdateMessage(updates
, &error
); 
 499                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 500                         CFReleaseNull(result
); 
 502                     CFReleaseNull(updates
); 
 505                 case sec_keychain_backup_syncable_id
: 
 507                 CFDictionaryRef oldbackup 
= NULL
; 
 508                 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) { 
 509                     CFDataRef keybag 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
); 
 511                         CFDataRef passcode 
= NULL
; 
 512                         if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) { 
 513                             CFDictionaryRef newbackup 
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
); 
 515                                 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
); 
 516                                 CFRelease(newbackup
); 
 518                             CFReleaseSafe(passcode
); 
 522                     CFReleaseSafe(oldbackup
); 
 526             case sec_keychain_restore_syncable_id
: 
 528                 CFDictionaryRef backup 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
); 
 530                     CFDataRef keybag 
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
); 
 532                         CFDataRef passcode 
= NULL
; 
 533                         if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) { 
 534                             bool result 
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
); 
 535                             xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 536                             CFReleaseSafe(passcode
); 
 544             case sec_ota_pki_asset_version_id
: 
 546                 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, 
 547                                          SecOTAPKIGetCurrentAssetVersion(&error
)); 
 550             case sec_add_shared_web_credential_id
: 
 552                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 554                     CFTypeRef result 
= NULL
; 
 555                     CFStringRef appID 
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
; 
 556                     if (_SecAddSharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) { 
 557                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 560                     CFReleaseSafe(appID
); 
 565             case sec_copy_shared_web_credential_id
: 
 567                 CFDictionaryRef query 
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
); 
 569                     CFTypeRef result 
= NULL
; 
 570                     CFStringRef appID 
= (clientTask
) ? SecTaskCopyApplicationIdentifier(clientTask
) : NULL
; 
 571                     if (_SecCopySharedWebCredential(query
, &auditToken
, appID
, domains
, &result
, &error
) && result
) { 
 572                         SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
); 
 575                     CFReleaseSafe(appID
); 
 580             case sec_get_log_settings_id
: 
 582                 CFPropertyListRef currentList 
= SecCopyLogSettings_Server(&error
); 
 584                     SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
); 
 586                 CFReleaseSafe(currentList
); 
 589             case sec_set_xpc_log_settings_id
: 
 591                 CFPropertyListRef newSettings 
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
); 
 593                     SecSetXPCLogSettings_Server(newSettings
, &error
); 
 595                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true); 
 596                 CFReleaseNull(newSettings
); 
 599             case sec_otr_session_create_remote_id
: 
 601                 CFDataRef publicPeerId 
= NULL
; 
 602                 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) { 
 603                     CFDataRef otrSession 
= _SecOTRSessionCreateRemote(publicPeerId
, &error
); 
 605                         SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
); 
 606                         CFRelease(otrSession
); 
 608                     CFReleaseSafe(publicPeerId
); 
 612             case sec_otr_session_process_packet_remote_id
: 
 614                 CFDataRef sessionData 
= NULL
, inputPacket 
= NULL
, outputSessionData 
= NULL
, outputPacket 
= NULL
; 
 615                 bool readyForMessages 
= false; 
 616                 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) { 
 617                     if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) { 
 618                         bool result 
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
); 
 620                             SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
); 
 621                             SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
); 
 622                             xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
); 
 623                             CFRelease(outputSessionData
); 
 624                             CFRelease(outputPacket
); 
 626                         xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
); 
 628                         CFReleaseSafe(inputPacket
); 
 630                     CFReleaseSafe(sessionData
); 
 634             case kSecXPCOpTryUserCredentials
: 
 635                 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) { 
 636                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 637                                             SOSCCTryUserCredentials_Server(label
, password
, &error
)); 
 640             case kSecXPCOpSetUserCredentials
: 
 641                 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) { 
 642                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 643                                             SOSCCSetUserCredentials_Server(label
, password
, &error
)); 
 646             case kSecXPCOpCanAuthenticate
: 
 647                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 648                                         SOSCCCanAuthenticate_Server(&error
)); 
 650             case kSecXPCOpPurgeUserCredentials
: 
 651                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 652                                         SOSCCPurgeUserCredentials_Server(&error
)); 
 654             case kSecXPCOpDeviceInCircle
: 
 655                 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, 
 656                                          SOSCCThisDeviceIsInCircle_Server(&error
)); 
 658             case kSecXPCOpRequestToJoin
: 
 659                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 660                                         SOSCCRequestToJoinCircle_Server(&error
)); 
 662             case kSecXPCOpRequestToJoinAfterRestore
: 
 663                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 664                                         SOSCCRequestToJoinCircleAfterRestore_Server(&error
)); 
 666             case kSecXPCOpRequestEnsureFreshParameters
: 
 667                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 668                                         SOSCCRequestEnsureFreshParameters_Server(&error
)); 
 670             case kSecXPCOpRequestDeviceID
: 
 672                 CFStringRef deviceID 
= SOSCCRequestDeviceID_Server(&error
); 
 674                     SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
); 
 678             case kSecXPCOpSetDeviceID
: 
 680                     secerror("securityd_xpc_dictionary_handler!"); 
 681                     CFStringRef IDS 
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
); 
 682                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
)); 
 686             case kSecXPCOpResetToOffering
: 
 687                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 688                                         SOSCCResetToOffering_Server(&error
)); 
 690             case kSecXPCOpResetToEmpty
: 
 691                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 692                                         SOSCCResetToEmpty_Server(&error
)); 
 694             case kSecXPCOpRemoveThisDeviceFromCircle
: 
 695                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 696                                         SOSCCRemoveThisDeviceFromCircle_Server(&error
)); 
 698             case kSecXPCOpBailFromCircle
: 
 700                 uint64_t limit_in_seconds 
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
); 
 701                 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 702                                         SOSCCBailFromCircle_Server(limit_in_seconds
, &error
)); 
 705             case kSecXPCOpAcceptApplicants
: 
 707                     xpc_object_t xapplicants 
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
); 
 708                     CFArrayRef applicants 
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); 
 709                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 710                                             (applicants 
&& SOSCCAcceptApplicants_Server(applicants
, &error
))); 
 711                     CFReleaseSafe(applicants
); 
 714             case kSecXPCOpRejectApplicants
: 
 716                     xpc_object_t xapplicants 
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfos
); 
 717                     CFArrayRef applicants 
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); 
 718                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 719                                             (applicants 
&& SOSCCRejectApplicants_Server(applicants
, &error
))); 
 720                     CFReleaseSafe(applicants
); 
 723             case kSecXPCOpCopyApplicantPeerInfo
: 
 725                     CFArrayRef array 
= SOSCCCopyApplicantPeerInfo_Server(&error
); 
 727                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 728                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 729                         xpc_release(xpc_array
); 
 731                     CFReleaseNull(array
); 
 734             case kSecXPCOpCopyValidPeerPeerInfo
: 
 736                     CFArrayRef array 
= SOSCCCopyValidPeerPeerInfo_Server(&error
); 
 738                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 739                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 740                         xpc_release(xpc_array
); 
 742                     CFReleaseNull(array
); 
 745             case kSecXPCOpValidateUserPublic
: 
 747                     bool trusted 
= SOSCCValidateUserPublic_Server(&error
); 
 748                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
); 
 751             case kSecXPCOpCopyNotValidPeerPeerInfo
: 
 753                     CFArrayRef array 
= SOSCCCopyNotValidPeerPeerInfo_Server(&error
); 
 755                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 756                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 757                         xpc_release(xpc_array
); 
 759                     CFReleaseNull(array
); 
 762             case kSecXPCOpCopyGenerationPeerInfo
: 
 764                     CFArrayRef array 
= SOSCCCopyGenerationPeerInfo_Server(&error
); 
 766                         xpc_object_t xpc_array 
= _CFXPCCreateXPCObjectFromCFObject(array
); 
 767                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 768                         xpc_release(xpc_array
); 
 770                     CFReleaseNull(array
); 
 773             case kSecXPCOpCopyRetirementPeerInfo
: 
 775                     CFArrayRef array 
= SOSCCCopyRetirementPeerInfo_Server(&error
); 
 777                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 778                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 779                         xpc_release(xpc_array
); 
 781                     CFReleaseNull(array
); 
 784             case kSecXPCOpCopyPeerPeerInfo
: 
 786                     CFArrayRef array 
= SOSCCCopyPeerPeerInfo_Server(&error
); 
 788                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 789                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 790                         xpc_release(xpc_array
); 
 792                     CFReleaseNull(array
); 
 795             case kSecXPCOpCopyConcurringPeerPeerInfo
: 
 797                     CFArrayRef array 
= SOSCCCopyConcurringPeerPeerInfo_Server(&error
); 
 799                         xpc_object_t xpc_array 
= CreateXPCObjectWithArrayOfPeerInfo(array
, &error
); 
 800                         xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 801                         xpc_release(xpc_array
); 
 803                     CFReleaseNull(array
); 
 806             case kSecXPCOpGetLastDepartureReason
: 
 807                 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, 
 808                                          SOSCCGetLastDepartureReason_Server(&error
)); 
 810             case kSecXPCOpProcessSyncWithAllPeers
: 
 811                 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, 
 812                                          SOSCCProcessSyncWithAllPeers_Server(&error
)); 
 814             case soscc_EnsurePeerRegistration_id
: 
 815                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 816                                              SOSCCProcessEnsurePeerRegistration_Server(&error
)); 
 818             case kSecXPCOpCopyIncompatibilityInfo
: { 
 819                 CFStringRef iis 
= SOSCCCopyIncompatibilityInfo_Server(&error
); 
 820                 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
); 
 824                         case kSecXPCOpOTAGetEscrowCertificates
: 
 826                     uint32_t escrowRootType 
= (uint32_t)xpc_dictionary_get_uint64(event
, "escrowType"); 
 827                                         CFArrayRef array 
= SecOTAPKICopyCurrentEscrowCertificates(escrowRootType
, &error
); 
 829                                                 xpc_object_t xpc_array 
= _CFXPCCreateXPCObjectFromCFObject(array
); 
 830                                                 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
); 
 831                             xpc_release(xpc_array
); 
 833                                         CFReleaseNull(array
); 
 836                         case kSecXPCOpOTAPKIGetNewAsset
: 
 837                                  xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, 
 838                                                  SecOTAPKISignalNewAsset(&error
)); 
 840             case kSecXPCOpRollKeys
: 
 842                     bool force 
= xpc_dictionary_get_bool(event
, "force"); 
 843                     xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, 
 844                                                  _SecServerRollKeys(force
, &error
)); 
 854             if(SecErrorGetOSStatus(error
) == errSecItemNotFound 
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
)) 
 855                 secdebug("ipc", "%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
); 
 857                 secerror("%@ %@ %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
); 
 859             xpcError 
= SecCreateXPCObjectWithCFError(error
); 
 860             xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
); 
 861         } else if (replyMessage
) { 
 862             secdebug("ipc", "%@ %@ responding %@", clientTask
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
); 
 865         SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
); 
 866         secerror("%@: returning error: %@", clientTask
, error
); 
 867         xpcError 
= SecCreateXPCObjectWithCFError(error
); 
 868         replyMessage 
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
); 
 872         xpc_connection_send_message(connection
, replyMessage
); 
 873         xpc_release(replyMessage
); 
 876         xpc_release(xpcError
); 
 877     CFReleaseSafe(error
); 
 878     CFReleaseSafe(accessGroups
); 
 879     CFReleaseSafe(domains
); 
 880     CFReleaseSafe(clientTask
); 
 883 static void securityd_xpc_init() 
 885     secdebug("serverxpc", "start"); 
 887     xpc_connection_t listener 
= xpc_connection_create_mach_service(kSecuritydXPCServiceName
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
); 
 889         seccritical("security failed to register xpc listener, exiting"); 
 893     xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) { 
 894         if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) { 
 895             xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) { 
 896                 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) { 
 897                     xpc_retain(connection
); 
 899                     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{ 
 900                         securityd_xpc_dictionary_handler(connection
, event
); 
 902                         xpc_release(connection
); 
 906             xpc_connection_resume(connection
); 
 909     xpc_connection_resume(listener
); 
 912 int main(int argc
, char *argv
[]) 
 914     char *wait4debugger 
= getenv("WAIT4DEBUGGER"); 
 915     if (wait4debugger 
&& !strcasecmp("YES", wait4debugger
)) { 
 916                 seccritical("SIGSTOPing self, awaiting debugger"); 
 917                 kill(getpid(), SIGSTOP
); 
 918                 asl_log(NULL
, NULL
, ASL_LEVEL_CRIT
, 
 919                 "Again, for good luck (or bad debuggers)"); 
 920                 kill(getpid(), SIGSTOP
); 
 923     securityd_init_server(); 
 924     securityd_xpc_init(); 
 925         dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, (NSEC_PER_SEC 
* 10)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), 
 927                 InitializeCloudKeychainTracing(); 
 933 /* vi:set ts=4 sw=4 et: */