1/* 2 * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 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> 51 52#include <AssertMacros.h> 53#include <CoreFoundation/CFXPCBridge.h> 54#include <CoreFoundation/CoreFoundation.h> 55#include <asl.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> 61#include <stdlib.h> 62#include <sys/queue.h> 63#include <sys/sysctl.h> 64#include <syslog.h> 65#include <xpc/private.h> 66#include <xpc/xpc.h> 67 68static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, 69 CFStringRef entitlement) 70{ 71 CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task, 72 entitlement, NULL); 73 if (value && CFGetTypeID(value) != CFStringGetTypeID()) { 74 CFRelease(value); 75 value = NULL; 76 } 77 78 return value; 79} 80 81static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, 82 CFStringRef entitlement) 83{ 84 CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task, 85 entitlement, NULL); 86 if (value) { 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()) { 92 CFRelease(value); 93 value = NULL; 94 break; 95 } 96 } 97 } else { 98 CFRelease(value); 99 value = NULL; 100 } 101 } 102 103 return value; 104} 105 106static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) { 107 return SecTaskCopyStringForEntitlement(task, 108 kSecEntitlementApplicationIdentifier); 109} 110 111static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) { 112 return SecTaskCopyArrayOfStringsForEntitlement(task, 113 kSecEntitlementAssociatedDomains); 114} 115 116static 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); 126 if (len) { 127 groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks); 128 if (kagLen) 129 CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, kagLen)); 130 if (appID) 131 CFArrayAppendValue(groups, appID); 132 if (asagLen) 133 CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, asagLen)); 134#if TARGET_IPHONE_SIMULATOR 135 } else { 136 secwarning("No keychain access group specified whilst running in simulator, falling back to default set"); 137 groups = (CFMutableArrayRef)CFRetainSafe(SecAccessGroupsGetCurrent()); 138#endif 139 } 140 141 CFReleaseSafe(appID); 142 CFReleaseSafe(keychainAccessGroups); 143 CFReleaseSafe(appleSecurityApplicationGroups); 144 return groups; 145} 146 147static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task, 148 CFStringRef entitlement) { 149 CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task, 150 entitlement, NULL); 151 if (!canModify) 152 return false; 153 CFTypeID canModifyType = CFGetTypeID(canModify); 154 bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify); 155 CFRelease(canModify); 156 return ok; 157} 158 159static 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); 161 162 size_t password_length = 0; 163 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length); 164 165 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull); 166 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8); 167 168 action(user_label, user_password); 169 170 CFReleaseNull(user_password); 171 CFReleaseNull(user_label); 172} 173 174static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) { 175 if (!path) 176 return true; 177 xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error); 178 if (!xpc_chain) 179 return false; 180 181 xpc_dictionary_set_value(message, key, xpc_chain); 182 xpc_release(xpc_chain); 183 return true; 184} 185 186static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) { 187 size_t length = 0; 188 const void *bytes = xpc_dictionary_get_data(message, key, &length); 189 if (bytes) { 190 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length); 191 if (certificate) 192 return certificate; 193 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key); 194 } else { 195 SecError(errSecParam, error, CFSTR("object for key %s missing"), key); 196 } 197 return NULL; 198} 199 200static 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; 206} 207 208static 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; 212 return true; 213 } 214 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); 215 return *certificates; 216} 217 218static 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); 220 if (!xpc_policies) { 221 if (policies) 222 *policies = NULL; 223 return true; 224 } 225 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error); 226 return *policies != NULL; 227} 228 229static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) { 230 SecTrustStoreRef ts = NULL; 231 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error); 232 if (domain) { 233 ts = SecTrustStoreForDomainName(domain, error); 234 CFRelease(domain); 235 } 236 return ts; 237} 238 239static 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); 243 } 244 return true; 245} 246 247static 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; 255 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); 260 261 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); 262 secdebug("serverxpc", "operation: %@ (%" PRIu64 ")", SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); 263 264 bool hasEntitlement; 265 audit_token_t auditToken = {}; 266 xpc_connection_get_audit_token(connection, &auditToken); 267 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); 272 } 273 274 // operations before kSecXPCOpTryUserCredentials don't need this entitlement. 275 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) || 276 (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle)); 277 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 280 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); 286 } 287 288 if (true) { 289 switch (operation) 290 { 291 case sec_item_add_id: 292 { 293 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 294 if (query) { 295 CFTypeRef result = NULL; 296 if (_SecItemAdd(query, accessGroups, &result, &error) && result) { 297 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 298 CFRelease(result); 299 } 300 CFRelease(query); 301 } 302 break; 303 } 304 case sec_item_copy_matching_id: 305 { 306 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 307 if (query) { 308 CFTypeRef result = NULL; 309 if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) { 310 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 311 CFRelease(result); 312 } 313 CFRelease(query); 314 } 315 break; 316 } 317 case sec_item_update_id: 318 { 319 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 320 if (query) { 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); 326 } 327 CFRelease(query); 328 } 329 break; 330 } 331 case sec_item_delete_id: 332 { 333 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 334 if (query) { 335 bool result = _SecItemDelete(query, accessGroups, &error); 336 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 337 CFRelease(query); 338 } 339 break; 340 } 341 case sec_trust_store_contains_id: 342 { 343 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 344 if (ts) { 345 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); 346 if (digest) { 347 bool contains; 348 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error)) 349 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains); 350 CFRelease(digest); 351 } 352 } 353 break; 354 } 355 case sec_trust_store_set_trust_settings_id: 356 { 357 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 358 if (ts) { 359 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error); 360 if (certificate) { 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); 366 } 367 CFRelease(certificate); 368 } 369 } 370 break; 371 } 372 case sec_trust_store_remove_certificate_id: 373 { 374 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 375 if (ts) { 376 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); 377 if (digest) { 378 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error); 379 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 380 CFRelease(digest); 381 } 382 } 383 break; 384 } 385 case sec_delete_all_id: 386 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error)); 387 break; 388 case sec_trust_evaluate_id: 389 { 390 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL; 391 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey); 392 double verifyTime; 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); 400 401 // Clear replyMessage so we don't send a synchronous reply. 402 xpc_object_t asyncReply = replyMessage; 403 replyMessage = NULL; 404 405 SecTrustServerEvaluateBlock(certificates, anchors, anchorsOnly, policies, verifyTime, accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) { 406 // Send back reply now 407 if (replyError) { 408 CFRetain(replyError); 409 } else { 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); 414 } 415 if (replyError) { 416 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); 417 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError); 418 if (xpcReplyError) { 419 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError); 420 xpc_release(xpcReplyError); 421 } 422 CFRelease(replyError); 423 } else { 424 secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); 425 } 426 427 xpc_connection_send_message(connection, asyncReply); 428 xpc_release(asyncReply); 429 xpc_release(connection); 430 CFReleaseSafe(clientTask); 431 }); 432 } 433 CFReleaseSafe(policies); 434 CFReleaseSafe(anchors); 435 CFReleaseSafe(certificates); 436 break; 437 } 438 case sec_keychain_backup_id: 439 { 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); 444 if (backup) { 445 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); 446 CFRelease(backup); 447 } 448 CFReleaseSafe(passcode); 449 } 450 CFReleaseSafe(keybag); 451 } 452 break; 453 } 454 case sec_keychain_restore_id: 455 { 456 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error); 457 if (backup) { 458 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 459 if (keybag) { 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); 465 } 466 CFRelease(keybag); 467 } 468 CFRelease(backup); 469 } 470 break; 471 } 472 case sec_keychain_sync_update_key_parameter_id: 473 { 474 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 475 if (updates) { 476 CFArrayRef result = _SecServerKeychainSyncUpdateKeyParameter(updates, &error); 477 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 478 CFReleaseNull(result); 479 } 480 CFReleaseNull(updates); 481 break; 482 } 483 case sec_keychain_sync_update_circle_id: 484 { 485 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 486 if (updates) { 487 CFArrayRef result = _SecServerKeychainSyncUpdateCircle(updates, &error); 488 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 489 CFReleaseNull(result); 490 } 491 CFReleaseNull(updates); 492 break; 493 } 494 case sec_keychain_sync_update_message_id: 495 { 496 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 497 if (updates) { 498 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error); 499 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 500 CFReleaseNull(result); 501 } 502 CFReleaseNull(updates); 503 break; 504 } 505 case sec_keychain_backup_syncable_id: 506 { 507 CFDictionaryRef oldbackup = NULL; 508 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) { 509 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 510 if (keybag) { 511 CFDataRef passcode = NULL; 512 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { 513 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error); 514 if (newbackup) { 515 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error); 516 CFRelease(newbackup); 517 } 518 CFReleaseSafe(passcode); 519 } 520 CFRelease(keybag); 521 } 522 CFReleaseSafe(oldbackup); 523 } 524 break; 525 } 526 case sec_keychain_restore_syncable_id: 527 { 528 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error); 529 if (backup) { 530 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 531 if (keybag) { 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); 537 } 538 CFRelease(keybag); 539 } 540 CFRelease(backup); 541 } 542 break; 543 } 544 case sec_ota_pki_asset_version_id: 545 { 546 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 547 SecOTAPKIGetCurrentAssetVersion(&error)); 548 break; 549 } 550 case sec_add_shared_web_credential_id: 551 { 552 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 553 if (query) { 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); 558 CFRelease(result); 559 } 560 CFReleaseSafe(appID); 561 CFRelease(query); 562 } 563 break; 564 } 565 case sec_copy_shared_web_credential_id: 566 { 567 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 568 if (query) { 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); 573 CFRelease(result); 574 } 575 CFReleaseSafe(appID); 576 CFRelease(query); 577 } 578 break; 579 } 580 case sec_get_log_settings_id: 581 { 582 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error); 583 if (currentList) { 584 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error); 585 } 586 CFReleaseSafe(currentList); 587 break; 588 } 589 case sec_set_xpc_log_settings_id: 590 { 591 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error); 592 if (newSettings) { 593 SecSetXPCLogSettings_Server(newSettings, &error); 594 } 595 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true); 596 CFReleaseNull(newSettings); 597 break; 598 } 599 case sec_otr_session_create_remote_id: 600 { 601 CFDataRef publicPeerId = NULL; 602 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) { 603 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error); 604 if (otrSession) { 605 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error); 606 CFRelease(otrSession); 607 } 608 CFReleaseSafe(publicPeerId); 609 } 610 break; 611 } 612 case sec_otr_session_process_packet_remote_id: 613 { 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); 619 if (result) { 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); 625 } 626 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 627 628 CFReleaseSafe(inputPacket); 629 } 630 CFReleaseSafe(sessionData); 631 } 632 break; 633 } 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)); 638 }); 639 break; 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)); 644 }); 645 break; 646 case kSecXPCOpCanAuthenticate: 647 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 648 SOSCCCanAuthenticate_Server(&error)); 649 break; 650 case kSecXPCOpPurgeUserCredentials: 651 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 652 SOSCCPurgeUserCredentials_Server(&error)); 653 break; 654 case kSecXPCOpDeviceInCircle: 655 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 656 SOSCCThisDeviceIsInCircle_Server(&error)); 657 break; 658 case kSecXPCOpRequestToJoin: 659 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 660 SOSCCRequestToJoinCircle_Server(&error)); 661 break; 662 case kSecXPCOpRequestToJoinAfterRestore: 663 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 664 SOSCCRequestToJoinCircleAfterRestore_Server(&error)); 665 break; 666 case kSecXPCOpRequestEnsureFreshParameters: 667 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 668 SOSCCRequestEnsureFreshParameters_Server(&error)); 669 break; 670 case kSecXPCOpRequestDeviceID: 671 { 672 CFStringRef deviceID = SOSCCRequestDeviceID_Server(&error); 673 if (deviceID) { 674 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error); 675 } 676 } 677 break; 678 case kSecXPCOpSetDeviceID: 679 { 680 secerror("securityd_xpc_dictionary_handler!"); 681 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error); 682 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error)); 683 CFReleaseNull(IDS); 684 } 685 break; 686 case kSecXPCOpResetToOffering: 687 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 688 SOSCCResetToOffering_Server(&error)); 689 break; 690 case kSecXPCOpResetToEmpty: 691 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 692 SOSCCResetToEmpty_Server(&error)); 693 break; 694 case kSecXPCOpRemoveThisDeviceFromCircle: 695 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 696 SOSCCRemoveThisDeviceFromCircle_Server(&error)); 697 break; 698 case kSecXPCOpBailFromCircle: 699 { 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)); 703 } 704 break; 705 case kSecXPCOpAcceptApplicants: 706 { 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); 712 } 713 break; 714 case kSecXPCOpRejectApplicants: 715 { 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); 721 } 722 break; 723 case kSecXPCOpCopyApplicantPeerInfo: 724 { 725 CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error); 726 if (array) { 727 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 728 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 729 xpc_release(xpc_array); 730 } 731 CFReleaseNull(array); 732 } 733 break; 734 case kSecXPCOpCopyValidPeerPeerInfo: 735 { 736 CFArrayRef array = SOSCCCopyValidPeerPeerInfo_Server(&error); 737 if (array) { 738 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 739 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 740 xpc_release(xpc_array); 741 } 742 CFReleaseNull(array); 743 } 744 break; 745 case kSecXPCOpValidateUserPublic: 746 { 747 bool trusted = SOSCCValidateUserPublic_Server(&error); 748 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted); 749 } 750 break; 751 case kSecXPCOpCopyNotValidPeerPeerInfo: 752 { 753 CFArrayRef array = SOSCCCopyNotValidPeerPeerInfo_Server(&error); 754 if (array) { 755 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 756 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 757 xpc_release(xpc_array); 758 } 759 CFReleaseNull(array); 760 } 761 break; 762 case kSecXPCOpCopyGenerationPeerInfo: 763 { 764 CFArrayRef array = SOSCCCopyGenerationPeerInfo_Server(&error); 765 if (array) { 766 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); 767 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 768 xpc_release(xpc_array); 769 } 770 CFReleaseNull(array); 771 } 772 break; 773 case kSecXPCOpCopyRetirementPeerInfo: 774 { 775 CFArrayRef array = SOSCCCopyRetirementPeerInfo_Server(&error); 776 if (array) { 777 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 778 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 779 xpc_release(xpc_array); 780 } 781 CFReleaseNull(array); 782 } 783 break; 784 case kSecXPCOpCopyPeerPeerInfo: 785 { 786 CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error); 787 if (array) { 788 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 789 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 790 xpc_release(xpc_array); 791 } 792 CFReleaseNull(array); 793 } 794 break; 795 case kSecXPCOpCopyConcurringPeerPeerInfo: 796 { 797 CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error); 798 if (array) { 799 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 800 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 801 xpc_release(xpc_array); 802 } 803 CFReleaseNull(array); 804 } 805 break; 806 case kSecXPCOpGetLastDepartureReason: 807 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 808 SOSCCGetLastDepartureReason_Server(&error)); 809 break; 810 case kSecXPCOpProcessSyncWithAllPeers: 811 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 812 SOSCCProcessSyncWithAllPeers_Server(&error)); 813 break; 814 case soscc_EnsurePeerRegistration_id: 815 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 816 SOSCCProcessEnsurePeerRegistration_Server(&error)); 817 break; 818 case kSecXPCOpCopyIncompatibilityInfo: { 819 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error); 820 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error); 821 CFReleaseSafe(iis); 822 break; 823 } 824 case kSecXPCOpOTAGetEscrowCertificates: 825 { 826 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType"); 827 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error); 828 if (array) { 829 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); 830 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 831 xpc_release(xpc_array); 832 } 833 CFReleaseNull(array); 834 } 835 break; 836 case kSecXPCOpOTAPKIGetNewAsset: 837 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 838 SecOTAPKISignalNewAsset(&error)); 839 break; 840 case kSecXPCOpRollKeys: 841 { 842 bool force = xpc_dictionary_get_bool(event, "force"); 843 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 844 _SecServerRollKeys(force, &error)); 845 } 846 break; 847 default: 848 break; 849 } 850 } 851 852 if (error) 853 { 854 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent)) 855 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); 856 else 857 secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); 858 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); 863 } 864 } else { 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); 869 } 870 871 if (replyMessage) { 872 xpc_connection_send_message(connection, replyMessage); 873 xpc_release(replyMessage); 874 } 875 if (xpcError) 876 xpc_release(xpcError); 877 CFReleaseSafe(error); 878 CFReleaseSafe(accessGroups); 879 CFReleaseSafe(domains); 880 CFReleaseSafe(clientTask); 881} 882 883static void securityd_xpc_init() 884{ 885 secdebug("serverxpc", "start"); 886 887 xpc_connection_t listener = xpc_connection_create_mach_service(kSecuritydXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); 888 if (!listener) { 889 seccritical("security failed to register xpc listener, exiting"); 890 abort(); 891 } 892 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); 898 xpc_retain(event); 899 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 900 securityd_xpc_dictionary_handler(connection, event); 901 xpc_release(event); 902 xpc_release(connection); 903 }); 904 } 905 }); 906 xpc_connection_resume(connection); 907 } 908 }); 909 xpc_connection_resume(listener); 910} 911 912int main(int argc, char *argv[]) 913{ 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); 921 } 922 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), 926 ^{ 927 InitializeCloudKeychainTracing(); 928 }); 929 dispatch_main(); 930 return 0; 931} 932 933/* vi:set ts=4 sw=4 et: */ 934