1/* 2 * Copyright (c) 2007-2013 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 <mach/mach.h> 25#include <mach/message.h> 26 27#include <stdlib.h> 28#include <sys/queue.h> 29 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> 36 37#include <asl.h> 38#include <syslog.h> 39#include <bsm/libbsm.h> 40#include <utilities/SecIOFormat.h> 41#include <utilities/debugging.h> 42 43#include "securityd_client.h" 44 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> 50 51#include <utilities/SecCFWrappers.h> 52#include <utilities/SecCFError.h> 53#include <utilities/SecXPCError.h> 54 55// TODO: Make this include work on both platforms. 56#if TARGET_OS_EMBEDDED 57#include <Security/SecEntitlements.h> 58#else 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") 65#else 66#define kSecEntitlementApplicationIdentifier CFSTR("com.apple.application-identifier") 67#endif 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") 78#endif 79 80#include <Security/SecuritydXPC.h> 81 82#include <libkern/OSAtomic.h> 83 84#include <CoreFoundation/CFXPCBridge.h> 85 86#include <xpc/xpc.h> 87#include <xpc/private.h> 88#include <xpc/connection_private.h> 89#include <AssertMacros.h> 90#include <SecureObjectSync/SOSCloudCircle.h> 91 92#include <securityd/SOSCloudCircleServer.h> 93#include <SecureObjectSync/SOSCloudCircleInternal.h> 94#include <sys/sysctl.h> 95 96// For SecError 97#include <utilities/SecDb.h> 98 99#include <securityd/OTATrustUtilities.h> 100 101 102#if TARGET_IPHONE_SIMULATOR 103#define CHECK_ENTITLEMENTS 0 104#else 105#define CHECK_ENTITLEMENTS 1 106#endif 107 108#if CHECK_ENTITLEMENTS 109static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, 110 CFStringRef entitlement) 111{ 112 CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task, 113 entitlement, NULL); 114 if (value && CFGetTypeID(value) != CFStringGetTypeID()) { 115 CFRelease(value); 116 value = NULL; 117 } 118 119 return value; 120} 121 122static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, 123 CFStringRef entitlement) 124{ 125 CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task, 126 entitlement, NULL); 127 if (value) { 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()) { 133 CFRelease(value); 134 value = NULL; 135 break; 136 } 137 } 138 } else { 139 CFRelease(value); 140 value = NULL; 141 } 142 } 143 144 return value; 145} 146 147#endif /* CHECK_ENTITLEMENTS */ 148 149static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { 150#if CHECK_ENTITLEMENTS 151 CFStringRef appID = SecTaskCopyStringForEntitlement(task, 152 kSecEntitlementApplicationIdentifier); 153 CFArrayRef groups = SecTaskCopyArrayOfStringsForEntitlement(task, 154 kSecEntitlementKeychainAccessGroups); 155 if (appID) { 156 if (groups) { 157 CFMutableArrayRef nGroups = CFArrayCreateMutableCopy( 158 CFGetAllocator(groups), CFArrayGetCount(groups) + 1, groups); 159 CFArrayAppendValue(nGroups, appID); 160 CFRelease(groups); 161 groups = nGroups; 162 } else { 163 groups = CFArrayCreate(CFGetAllocator(task), 164 (const void **)&appID, 1, &kCFTypeArrayCallBacks); 165 } 166 CFRelease(appID); 167 } 168#else 169 CFArrayRef groups = SecAccessGroupsGetCurrent(); 170 if (groups) 171 CFRetain(groups); 172#endif 173 return groups; 174} 175 176static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task, 177 CFStringRef entitlement) { 178#if CHECK_ENTITLEMENTS 179 CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task, 180 entitlement, NULL); 181 if (!canModify) 182 return false; 183 CFTypeID canModifyType = CFGetTypeID(canModify); 184 bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify); 185 CFRelease(canModify); 186 return ok; 187#else 188 return true; 189#endif /* !CHECK_ENTITLEMENTS */ 190} 191 192static 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); 194 195 size_t password_length = 0; 196 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length); 197 198 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull); 199 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8); 200 201 action(user_label, user_password); 202 203 CFReleaseNull(user_password); 204 CFReleaseNull(user_label); 205} 206 207static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) { 208 if (!path) 209 return true; 210 xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error); 211 if (!xpc_chain) 212 return false; 213 214 xpc_dictionary_set_value(message, key, xpc_chain); 215 xpc_release(xpc_chain); 216 return true; 217} 218 219static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) { 220 size_t length = 0; 221 const void *bytes = xpc_dictionary_get_data(message, key, &length); 222 if (bytes) { 223 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length); 224 if (certificate) 225 return certificate; 226 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key); 227 } else { 228 SecError(errSecParam, error, CFSTR("object for key %s missing"), key); 229 } 230 return NULL; 231} 232 233static 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; 239} 240 241static 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; 245 return true; 246 } 247 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); 248 return *certificates; 249} 250 251static 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); 253 if (!xpc_policies) { 254 if (policies) 255 *policies = NULL; 256 return true; 257 } 258 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error); 259 return *policies != NULL; 260} 261 262static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) { 263 SecTrustStoreRef ts = NULL; 264 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error); 265 if (domain) { 266 ts = SecTrustStoreForDomainName(domain, error); 267 CFRelease(domain); 268 } 269 return ts; 270} 271 272static 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); 276 } 277 return true; 278} 279 280static 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; 287 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); 292 293 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); 294 secdebug("serverxpc", "operation: %@ (%" PRIu64 ")", SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); 295 296 bool hasEntitlement; 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); 302 303 // operations before kSecXPCOpTryUserCredentials don't need this entitlement. 304 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) || 305 (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle)); 306#else 307 clientTask = NULL; 308 hasEntitlement = true; 309#endif 310 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 313 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); 319 } 320 321 if (true) { 322 switch (operation) 323 { 324 case sec_item_add_id: 325 { 326 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 327 if (query) { 328 CFTypeRef result = NULL; 329 if (_SecItemAdd(query, accessGroups, &result, &error) && result) { 330 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 331 CFRelease(result); 332 } 333 CFRelease(query); 334 } 335 break; 336 } 337 case sec_item_copy_matching_id: 338 { 339 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 340 if (query) { 341 CFTypeRef result = NULL; 342 if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) { 343 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); 344 CFRelease(result); 345 } 346 CFRelease(query); 347 } 348 break; 349 } 350 case sec_item_update_id: 351 { 352 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 353 if (query) { 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); 359 } 360 CFRelease(query); 361 } 362 break; 363 } 364 case sec_item_delete_id: 365 { 366 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 367 if (query) { 368 bool result = _SecItemDelete(query, accessGroups, &error); 369 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 370 CFRelease(query); 371 } 372 break; 373 } 374 case sec_trust_store_contains_id: 375 { 376 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 377 if (ts) { 378 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); 379 if (digest) { 380 bool contains; 381 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error)) 382 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains); 383 CFRelease(digest); 384 } 385 } 386 break; 387 } 388 case sec_trust_store_set_trust_settings_id: 389 { 390 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 391 if (ts) { 392 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error); 393 if (certificate) { 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); 399 } 400 CFRelease(certificate); 401 } 402 } 403 break; 404 } 405 case sec_trust_store_remove_certificate_id: 406 { 407 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); 408 if (ts) { 409 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); 410 if (digest) { 411 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error); 412 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 413 CFRelease(digest); 414 } 415 } 416 break; 417 } 418 case sec_delete_all_id: 419 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error)); 420 break; 421 case sec_trust_evaluate_id: 422 { 423 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL; 424 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey); 425 double verifyTime; 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); 433 434 // Clear replyMessage so we don't send a synchronous reply. 435 xpc_object_t asyncReply = replyMessage; 436 replyMessage = NULL; 437 438 SecTrustServerEvaluateBlock(certificates, anchors, anchorsOnly, policies, verifyTime, accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) { 439 // Send back reply now 440 if (replyError) { 441 CFRetain(replyError); 442 } else { 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); 447 } 448 if (replyError) { 449 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); 450 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError); 451 if (xpcReplyError) { 452 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError); 453 xpc_release(xpcReplyError); 454 } 455 CFRelease(replyError); 456 } else { 457 secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); 458 } 459 460 xpc_connection_send_message(connection, asyncReply); 461 xpc_release(asyncReply); 462 xpc_release(connection); 463 CFReleaseSafe(clientTask); 464 }); 465 } 466 CFReleaseSafe(policies); 467 CFReleaseSafe(anchors); 468 CFReleaseSafe(certificates); 469 break; 470 } 471 case sec_keychain_backup_id: 472 { 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); 477 if (backup) { 478 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); 479 CFRelease(backup); 480 } 481 CFReleaseSafe(passcode); 482 } 483 CFReleaseSafe(keybag); 484 } 485 break; 486 } 487 case sec_keychain_restore_id: 488 { 489 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error); 490 if (backup) { 491 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 492 if (keybag) { 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); 498 } 499 CFRelease(keybag); 500 } 501 CFRelease(backup); 502 } 503 break; 504 } 505 case sec_keychain_sync_update_id: 506 { 507 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); 508 if (updates) { 509 bool result = _SecServerKeychainSyncUpdate(updates, &error); 510 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); 511 CFRelease(updates); 512 } 513 break; 514 } 515 case sec_keychain_backup_syncable_id: 516 { 517 CFDictionaryRef oldbackup = NULL; 518 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) { 519 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 520 if (keybag) { 521 CFDataRef passcode = NULL; 522 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { 523 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error); 524 if (newbackup) { 525 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error); 526 CFRelease(newbackup); 527 } 528 CFReleaseSafe(passcode); 529 } 530 CFRelease(keybag); 531 } 532 CFReleaseSafe(oldbackup); 533 } 534 break; 535 } 536 case sec_keychain_restore_syncable_id: 537 { 538 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error); 539 if (backup) { 540 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); 541 if (keybag) { 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); 547 } 548 CFRelease(keybag); 549 } 550 CFRelease(backup); 551 } 552 break; 553 } 554 case sec_ota_pki_asset_version_id: 555 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 556 SecOTAPKIGetCurrentAssetVersion(&error)); 557 break; 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)); 562 }); 563 break; 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)); 568 }); 569 break; 570 case kSecXPCOpCanAuthenticate: 571 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 572 SOSCCCanAuthenticate_Server(&error)); 573 break; 574 case kSecXPCOpPurgeUserCredentials: 575 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 576 SOSCCPurgeUserCredentials_Server(&error)); 577 break; 578 case kSecXPCOpDeviceInCircle: 579 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 580 SOSCCThisDeviceIsInCircle_Server(&error)); 581 break; 582 case kSecXPCOpRequestToJoin: 583 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 584 SOSCCRequestToJoinCircle_Server(&error)); 585 break; 586 case kSecXPCOpRequestToJoinAfterRestore: 587 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 588 SOSCCRequestToJoinCircleAfterRestore_Server(&error)); 589 break; 590 case kSecXPCOpResetToOffering: 591 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 592 SOSCCResetToOffering_Server(&error)); 593 break; 594 case kSecXPCOpResetToEmpty: 595 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 596 SOSCCResetToEmpty_Server(&error)); 597 break; 598 case kSecXPCOpRemoveThisDeviceFromCircle: 599 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 600 SOSCCRemoveThisDeviceFromCircle_Server(&error)); 601 break; 602 case kSecXPCOpBailFromCircle: 603 { 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)); 607 } 608 break; 609 case kSecXPCOpAcceptApplicants: 610 { 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); 616 } 617 break; 618 case kSecXPCOpRejectApplicants: 619 { 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); 625 } 626 break; 627 case kSecXPCOpCopyApplicantPeerInfo: 628 { 629 CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error); 630 if (array) { 631 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 632 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 633 xpc_release(xpc_array); 634 } 635 CFReleaseNull(array); 636 } 637 break; 638 case kSecXPCOpCopyPeerPeerInfo: 639 { 640 CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error); 641 if (array) { 642 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 643 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 644 xpc_release(xpc_array); 645 } 646 CFReleaseNull(array); 647 } 648 break; 649 case kSecXPCOpCopyConcurringPeerPeerInfo: 650 { 651 CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error); 652 if (array) { 653 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); 654 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 655 xpc_release(xpc_array); 656 } 657 CFReleaseNull(array); 658 } 659 break; 660 case kSecXPCOpGetLastDepartureReason: 661 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 662 SOSCCGetLastDepartureReason_Server(&error)); 663 break; 664 case kSecXPCOpProcessSyncWithAllPeers: 665 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 666 SOSCCProcessSyncWithAllPeers_Server(&error)); 667 break; 668 case kSecXPCOpCopyIncompatibilityInfo: 669 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, 670 SOSCCCopyIncompatibilityInfo_Server(&error)); 671 break; 672 case kSecXPCOpOTAGetEscrowCertificates: 673 { 674 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(&error); 675 if (array) { 676 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); 677 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); 678 xpc_release(xpc_array); 679 } 680 CFReleaseNull(array); 681 } 682 break; 683 case kSecXPCOpOTAPKIGetNewAsset: 684 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, 685 SecOTAPKISignalNewAsset(&error)); 686 break; 687 default: 688 break; 689 } 690 } 691 692 if (error) 693 { 694 if(SecErrorGetOSStatus(error) == errSecItemNotFound) 695 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); 696 else 697 secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); 698 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); 703 } 704 } else { 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); 709 } 710 711 if (replyMessage) { 712 xpc_connection_send_message(connection, replyMessage); 713 xpc_release(replyMessage); 714 } 715 if (xpcError) 716 xpc_release(xpcError); 717 CFReleaseSafe(error); 718 CFReleaseSafe(accessGroups); 719 CFReleaseSafe(clientTask); 720} 721 722static void securityd_xpc_init() 723{ 724 secdebug("serverxpc", "start"); 725 726 xpc_track_activity(); 727 xpc_connection_t listener = xpc_connection_create_mach_service(kSecuritydXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); 728 if (!listener) { 729 seccritical("security failed to register xpc listener, exiting"); 730 abort(); 731 } 732 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); 738 xpc_retain(event); 739 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 740 securityd_xpc_dictionary_handler(connection, event); 741 xpc_release(event); 742 xpc_release(connection); 743 }); 744 } 745 }); 746 xpc_connection_resume(connection); 747 } 748 }); 749 xpc_connection_resume(listener); 750} 751 752int main(int argc, char *argv[]) 753{ 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); 761 } 762 763 securityd_init_server(); 764 securityd_xpc_init(); 765 dispatch_main(); 766 return 0; 767} 768 769/* vi:set ts=4 sw=4 et: */ 770