SecKeychain.cpp
1 /* 2 * Copyright (c) 2000-2004,2011-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 <Security/SecKeychain.h> 25 #include <Security/SecKeychainPriv.h> 26 #include <security_keychain/KCCursor.h> 27 #include <security_cdsa_utilities/cssmdata.h> 28 #include <security_cdsa_client/wrapkey.h> 29 #include <security_keychain/KCExceptions.h> 30 #include <securityd_client/ssblob.h> 31 #include <Security/SecAccess.h> 32 #include <Security/SecTrustedApplicationPriv.h> 33 #include "SecBridge.h" 34 #include "CCallbackMgr.h" 35 #include <security_cdsa_utilities/Schema.h> 36 #include <security_cdsa_client/mdsclient.h> 37 #include <pwd.h> 38 #include <os/activity.h> 39 #include <Security/AuthorizationTagsPriv.h> 40 #include <Security/Authorization.h> 41 #include "TokenLogin.h" 42 #include "LegacyAPICounts.h" 43 44 extern "C" { 45 #include "ctkloginhelper.h" 46 } 47 48 OSStatus 49 SecKeychainMDSInstall() 50 { 51 BEGIN_SECAPI 52 53 os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 54 os_activity_scope(activity); 55 os_release(activity); 56 57 Security::MDSClient::Directory d; 58 d.install(); 59 60 END_SECAPI 61 } 62 63 CFTypeID 64 SecKeychainGetTypeID(void) 65 { 66 BEGIN_SECAPI 67 68 return gTypes().KeychainImpl.typeID; 69 70 END_SECAPI1(_kCFRuntimeNotATypeID) 71 } 72 73 74 OSStatus 75 SecKeychainGetVersion(UInt32 *returnVers) 76 { 77 COUNTLEGACYAPI 78 if (!returnVers) 79 return errSecSuccess; 80 81 *returnVers = 0x02028000; 82 return errSecSuccess; 83 } 84 85 86 OSStatus 87 SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef) 88 { 89 BEGIN_SECAPI 90 91 os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 92 os_activity_scope(activity); 93 os_release(activity); 94 95 RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle(); 96 97 END_SECAPI 98 } 99 100 OSStatus 101 SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password, 102 Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef) 103 { 104 BEGIN_SECAPI 105 106 os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 107 os_activity_scope(activity); 108 os_release(activity); 109 110 KCThrowParamErrIf_(!pathName); 111 Keychain keychain = globals().storageManager.make(pathName, true, true); 112 113 // @@@ the call to StorageManager::make above leaves keychain the the cache. 114 // If the create below fails we should probably remove it. 115 if(promptUser) 116 keychain->create(); 117 else 118 { 119 KCThrowParamErrIf_(!password); 120 keychain->create(passwordLength, password); 121 } 122 123 RequiredParam(keychainRef)=keychain->handle(); 124 125 END_SECAPI 126 } 127 128 129 OSStatus 130 SecKeychainDelete(SecKeychainRef keychainOrArray) 131 { 132 BEGIN_SECAPI 133 134 os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 135 os_activity_scope(activity); 136 os_release(activity); 137 138 KCThrowIf_(!keychainOrArray, errSecInvalidKeychain); 139 StorageManager::KeychainList keychains; 140 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 141 142 globals().storageManager.remove(keychains, true); 143 144 END_SECAPI 145 } 146 147 148 OSStatus 149 SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings) 150 { 151 BEGIN_SECAPI 152 153 os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 154 os_activity_scope(activity); 155 os_release(activity); 156 157 Keychain keychain = Keychain::optional(keychainRef); 158 if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1) 159 { 160 UInt32 lockInterval=newSettings->lockInterval; 161 bool lockOnSleep=newSettings->lockOnSleep; 162 keychain->setSettings(lockInterval, lockOnSleep); 163 } 164 165 END_SECAPI 166 } 167 168 169 OSStatus 170 SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings) 171 { 172 BEGIN_SECAPI 173 174 os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 175 os_activity_scope(activity); 176 os_release(activity); 177 178 Keychain keychain = Keychain::optional(keychainRef); 179 if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1) 180 { 181 uint32 lockInterval; 182 bool lockOnSleep; 183 184 keychain->getSettings(lockInterval, lockOnSleep); 185 outSettings->lockInterval=lockInterval; 186 outSettings->lockOnSleep=lockOnSleep; 187 } 188 189 END_SECAPI 190 } 191 192 193 OSStatus 194 SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void *password, Boolean usePassword) 195 { 196 BEGIN_SECAPI 197 198 os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 199 os_activity_scope(activity); 200 os_release(activity); 201 202 Keychain keychain = Keychain::optional(keychainRef); 203 204 if (usePassword) 205 keychain->unlock(CssmData(const_cast<void *>(password), passwordLength)); 206 else 207 keychain->unlock(); 208 209 END_SECAPI 210 } 211 212 213 OSStatus 214 SecKeychainLock(SecKeychainRef keychainRef) 215 { 216 BEGIN_SECAPI 217 218 os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 219 os_activity_scope(activity); 220 os_release(activity); 221 222 Keychain keychain = Keychain::optional(keychainRef); 223 keychain->lock(); 224 225 END_SECAPI 226 } 227 228 229 OSStatus 230 SecKeychainLockAll(void) 231 { 232 BEGIN_SECAPI 233 234 os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 235 os_activity_scope(activity); 236 os_release(activity); 237 238 globals().storageManager.lockAll(); 239 240 END_SECAPI 241 } 242 243 244 OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList) 245 { 246 BEGIN_SECAPI 247 248 os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 249 os_activity_scope(activity); 250 os_release(activity); 251 // 252 // Get the current user (using fallback method if necessary) 253 // 254 char* uName = getenv("USER"); 255 string userName = uName ? uName : ""; 256 if ( userName.length() == 0 ) 257 { 258 uid_t uid = geteuid(); 259 if (!uid) uid = getuid(); 260 struct passwd *pw = getpwuid(uid); // fallback case... 261 if (pw) 262 userName = pw->pw_name; 263 endpwent(); 264 } 265 if ( userName.length() == 0 ) // did we ultimately get one? 266 { 267 MacOSError::throwMe(errAuthorizationInternal); 268 } 269 270 SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData()); 271 secwarning("SecKeychainResetLogin: reset AKS passphrase"); 272 if (password) 273 { 274 // Clear the plist and move aside (rename) the existing login.keychain 275 globals().storageManager.resetKeychain(resetSearchList); 276 277 // Create the login keychain without UI 278 globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password, true); 279 280 // Set it as the default 281 Keychain keychain = globals().storageManager.loginKeychain(); 282 globals().storageManager.defaultKeychain(keychain); 283 } 284 else 285 { 286 // Create the login keychain, prompting for password 287 // (implicitly calls resetKeychain, login, and defaultKeychain) 288 globals().storageManager.makeLoginAuthUI(NULL, true); 289 } 290 secwarning("SecKeychainResetLogin: reset osx keychain"); 291 292 // Post a "list changed" event after a reset, so apps can refresh their list. 293 // Make sure we are not holding mLock when we post this event. 294 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent); 295 296 297 END_SECAPI 298 } 299 300 OSStatus 301 SecKeychainCopyDefault(SecKeychainRef *keychainRef) 302 { 303 BEGIN_SECAPI 304 305 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain()->handle(); 306 307 END_SECAPI 308 } 309 310 311 OSStatus 312 SecKeychainSetDefault(SecKeychainRef keychainRef) 313 { 314 BEGIN_SECAPI 315 316 os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 317 os_activity_scope(activity); 318 os_release(activity); 319 320 globals().storageManager.defaultKeychain(Keychain::optional(keychainRef)); 321 322 END_SECAPI 323 } 324 325 OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) 326 { 327 BEGIN_SECAPI 328 329 os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 330 os_activity_scope(activity); 331 os_release(activity); 332 333 RequiredParam(searchList); 334 StorageManager &smr = globals().storageManager; 335 StorageManager::KeychainList keychainList; 336 smr.getSearchList(keychainList); 337 *searchList = smr.convertFromKeychainList(keychainList); 338 339 END_SECAPI 340 } 341 342 OSStatus SecKeychainSetSearchList(CFArrayRef searchList) 343 { 344 BEGIN_SECAPI 345 346 os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 347 os_activity_scope(activity); 348 os_release(activity); 349 350 RequiredParam(searchList); 351 StorageManager &smr = globals().storageManager; 352 StorageManager::KeychainList keychainList; 353 smr.convertToKeychainList(searchList, keychainList); 354 smr.setSearchList(keychainList); 355 356 END_SECAPI 357 } 358 359 OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef) 360 { 361 BEGIN_SECAPI 362 363 os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 364 os_activity_scope(activity); 365 os_release(activity); 366 367 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle(); 368 369 END_SECAPI 370 } 371 372 OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef) 373 { 374 BEGIN_SECAPI 375 376 os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 377 os_activity_scope(activity); 378 os_release(activity); 379 380 globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef)); 381 382 END_SECAPI 383 } 384 385 OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef *searchList) 386 { 387 BEGIN_SECAPI 388 389 RequiredParam(searchList); 390 StorageManager &smr = globals().storageManager; 391 StorageManager::KeychainList keychainList; 392 smr.getSearchList(domain, keychainList); 393 *searchList = smr.convertFromKeychainList(keychainList); 394 395 END_SECAPI 396 } 397 398 OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList) 399 { 400 BEGIN_SECAPI 401 402 os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 403 os_activity_scope(activity); 404 os_release(activity); 405 406 RequiredParam(searchList); 407 StorageManager &smr = globals().storageManager; 408 StorageManager::KeychainList keychainList; 409 smr.convertToKeychainList(searchList, keychainList); 410 smr.setSearchList(domain, keychainList); 411 412 END_SECAPI 413 } 414 415 OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) 416 { 417 BEGIN_SECAPI 418 419 os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 420 os_activity_scope(activity); 421 os_release(activity); 422 423 globals().storageManager.domain(domain); 424 425 END_SECAPI 426 } 427 428 OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain) 429 { 430 BEGIN_SECAPI 431 432 os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 433 os_activity_scope(activity); 434 os_release(activity); 435 436 *domain = globals().storageManager.domain(); 437 438 END_SECAPI 439 } 440 441 442 OSStatus 443 SecKeychainGetStatus(SecKeychainRef keychainRef, SecKeychainStatus *keychainStatus) 444 { 445 BEGIN_SECAPI 446 447 RequiredParam(keychainStatus) = (SecKeychainStatus)Keychain::optional(keychainRef)->status(); 448 449 END_SECAPI 450 } 451 452 453 OSStatus 454 SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathName) 455 { 456 BEGIN_SECAPI 457 458 RequiredParam(pathName); 459 RequiredParam(ioPathLength); 460 461 const char *name = Keychain::optional(keychainRef)->name(); 462 UInt32 nameLen = (UInt32)strlen(name); 463 UInt32 callersLen = *ioPathLength; 464 *ioPathLength = nameLen; 465 if (nameLen+1 > callersLen) // if the client's buffer is too small (including null-termination), throw 466 return errSecBufferTooSmall; 467 strncpy(pathName, name, nameLen); 468 pathName[nameLen] = 0; 469 *ioPathLength = nameLen; // set the length. 470 471 END_SECAPI 472 } 473 474 OSStatus 475 SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version) 476 { 477 BEGIN_SECAPI 478 479 RequiredParam(version); 480 481 *version = Keychain::optional(keychainRef)->database()->dbBlobVersion(); 482 483 END_SECAPI 484 } 485 486 OSStatus 487 SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename) 488 { 489 BEGIN_SECAPI 490 491 os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 492 os_activity_scope(activity); 493 os_release(activity); 494 495 RequiredParam(masterKeyFilename); 496 Keychain kc = Keychain::optional(keychain); 497 498 SecurityServer::SystemKeychainKey keychainKey(masterKeyFilename); 499 if(keychainKey.valid()) { 500 // We've managed to read the key; now, create credentials using it 501 string path = kc->name(); 502 503 CssmClient::Key keychainMasterKey(kc->csp(), keychainKey.key(), true); 504 CssmClient::AclFactory::MasterKeyUnlockCredentials creds(keychainMasterKey, Allocator::standard(Allocator::sensitive)); 505 506 // Attempt the migrate, using our master key as the ACL override 507 bool result = kc->keychainMigration(path, kc->database()->dbBlobVersion(), path, version, creds.getAccessCredentials()); 508 if(!result) { 509 return errSecBadReq; 510 } 511 return (kc->database()->dbBlobVersion() == version ? errSecSuccess : errSecBadReq); 512 } else { 513 return errSecBadReq; 514 } 515 516 END_SECAPI 517 } 518 519 520 // @@@ Deprecated 521 UInt16 522 SecKeychainListGetCount(void) 523 { 524 BEGIN_SECAPI 525 526 return globals().storageManager.size(); 527 528 END_SECAPI1(0) 529 } 530 531 532 // @@@ Deprecated 533 OSStatus 534 SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef) 535 { 536 BEGIN_SECAPI 537 538 KeychainCore::StorageManager &smgr=KeychainCore::globals().storageManager; 539 RequiredParam(keychainRef)=smgr[index]->handle(); 540 541 END_SECAPI 542 } 543 544 545 // @@@ Deprecated 546 OSStatus 547 SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef) 548 { 549 BEGIN_SECAPI 550 551 Required(keychainRef); 552 Keychain keychain = Keychain::optional(*keychainRef); 553 StorageManager::KeychainList keychainList; 554 keychainList.push_back(keychain); 555 globals().storageManager.remove(keychainList); 556 *keychainRef = NULL; 557 558 END_SECAPI 559 } 560 561 562 OSStatus 563 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef, UInt32 itemID, SecKeychainAttributeInfo **info) 564 { 565 BEGIN_SECAPI 566 567 Keychain keychain = Keychain::optional(keychainRef); 568 keychain->getAttributeInfoForItemID(itemID, info); 569 570 END_SECAPI 571 } 572 573 574 OSStatus 575 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) 576 { 577 BEGIN_SECAPI 578 579 KeychainImpl::freeAttributeInfo(info); 580 581 END_SECAPI 582 } 583 584 585 pascal OSStatus 586 SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext) 587 { 588 BEGIN_SECAPI 589 590 os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 591 os_activity_scope(activity); 592 os_release(activity); 593 594 RequiredParam(callbackFunction); 595 CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext); 596 597 END_SECAPI 598 } 599 600 601 OSStatus 602 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) 603 { 604 BEGIN_SECAPI 605 606 os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 607 os_activity_scope(activity); 608 os_release(activity); 609 610 RequiredParam(callbackFunction); 611 CCallbackMgr::RemoveCallback(callbackFunction); 612 613 END_SECAPI 614 } 615 616 OSStatus 617 SecKeychainAddInternetPassword(SecKeychainRef keychainRef, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) 618 { 619 BEGIN_SECAPI 620 621 os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 622 os_activity_scope(activity); 623 os_release(activity); 624 625 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL); 626 // @@@ Get real itemClass 627 Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false); 628 629 if (serverName && serverNameLength) 630 { 631 CssmData server(const_cast<void *>(reinterpret_cast<const void *>(serverName)), serverNameLength); 632 item->setAttribute(Schema::attributeInfo(kSecServerItemAttr), server); 633 // use server name as default label 634 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), server); 635 } 636 637 if (accountName && accountNameLength) 638 { 639 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength); 640 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); 641 } 642 643 if (securityDomain && securityDomainLength) 644 item->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr), 645 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain)), securityDomainLength)); 646 647 item->setAttribute(Schema::attributeInfo(kSecPortItemAttr), UInt32(port)); 648 item->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr), protocol); 649 item->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr), authenticationType); 650 651 if (path && pathLength) 652 item->setAttribute(Schema::attributeInfo(kSecPathItemAttr), 653 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path)), pathLength)); 654 655 Keychain keychain = nil; 656 try 657 { 658 keychain = Keychain::optional(keychainRef); 659 if ( !keychain->exists() ) 660 { 661 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. 662 } 663 } 664 catch(...) 665 { 666 keychain = globals().storageManager.defaultKeychainUI(item); 667 } 668 669 keychain->add(item); 670 671 if (itemRef) 672 *itemRef = item->handle(); 673 674 END_SECAPI 675 } 676 677 678 OSStatus 679 SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef) 680 681 { 682 BEGIN_SECAPI 683 684 os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 685 os_activity_scope(activity); 686 os_release(activity); 687 688 StorageManager::KeychainList keychains; 689 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 690 KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL); 691 692 if (serverName && serverNameLength) 693 { 694 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServerItemAttr), 695 CssmData(const_cast<char *>(serverName), serverNameLength)); 696 } 697 698 if (securityDomain && securityDomainLength) 699 { 700 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecSecurityDomainItemAttr), 701 CssmData (const_cast<char*>(securityDomain), securityDomainLength)); 702 } 703 704 if (accountName && accountNameLength) 705 { 706 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr), 707 CssmData (const_cast<char*>(accountName), accountNameLength)); 708 } 709 710 if (port) 711 { 712 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPortItemAttr), 713 UInt32(port)); 714 } 715 716 if (protocol) 717 { 718 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecProtocolItemAttr), 719 protocol); 720 } 721 722 if (authenticationType) 723 { 724 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAuthenticationTypeItemAttr), 725 authenticationType); 726 } 727 728 if (path && pathLength) 729 { 730 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPathItemAttr), path); 731 } 732 733 Item item; 734 if (!cursor->next(item)) 735 return errSecItemNotFound; 736 737 // Get its data (only if necessary) 738 if (passwordData || passwordLength) 739 { 740 CssmDataContainer outData; 741 item->getData(outData); 742 if (passwordLength) { 743 *passwordLength=(UInt32)outData.length(); 744 } 745 outData.Length=0; 746 if (passwordData) { 747 *passwordData=outData.data(); 748 } 749 outData.Data=NULL; 750 } 751 752 if (itemRef) 753 *itemRef=item->handle(); 754 755 END_SECAPI 756 } 757 758 759 OSStatus 760 SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) 761 { 762 BEGIN_SECAPI 763 764 os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 765 os_activity_scope(activity); 766 os_release(activity); 767 768 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL); 769 // @@@ Get real itemClass 770 771 Item item(kSecGenericPasswordItemClass, 'aapl', passwordLength, passwordData, false); 772 773 if (serviceName && serviceNameLength) 774 { 775 CssmData service(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength); 776 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); 777 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); 778 } 779 780 if (accountName && accountNameLength) 781 { 782 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength); 783 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); 784 } 785 786 Keychain keychain = nil; 787 try 788 { 789 keychain = Keychain::optional(keychainRef); 790 if ( !keychain->exists() ) 791 { 792 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. 793 } 794 } 795 catch(...) 796 { 797 keychain = globals().storageManager.defaultKeychainUI(item); 798 } 799 800 keychain->add(item); 801 if (itemRef) 802 *itemRef = item->handle(); 803 804 END_SECAPI 805 } 806 807 808 OSStatus 809 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef) 810 811 { 812 BEGIN_SECAPI 813 814 os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 815 os_activity_scope(activity); 816 os_release(activity); 817 818 StorageManager::KeychainList keychains; 819 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 820 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); 821 822 if (serviceName && serviceNameLength) 823 { 824 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), 825 CssmData(const_cast<char *>(serviceName), serviceNameLength)); 826 } 827 828 if (accountName && accountNameLength) 829 { 830 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr), 831 CssmData(const_cast<char *>(accountName), accountNameLength)); 832 } 833 834 Item item; 835 if (!cursor->next(item)) 836 return errSecItemNotFound; 837 838 // Get its data (only if necessary) 839 if (passwordData || passwordLength) 840 { 841 CssmDataContainer outData; 842 item->getData(outData); 843 if (passwordLength) { 844 *passwordLength=(UInt32)outData.length(); 845 } 846 outData.Length=0; 847 if (passwordData) { 848 *passwordData=outData.data(); 849 } 850 outData.Data=NULL; 851 } 852 853 if (itemRef) 854 *itemRef=item->handle(); 855 856 END_SECAPI 857 } 858 859 860 OSStatus 861 SecKeychainSetUserInteractionAllowed(Boolean state) 862 { 863 BEGIN_SECAPI 864 865 globals().setUserInteractionAllowed(state); 866 867 END_SECAPI 868 } 869 870 871 OSStatus 872 SecKeychainGetUserInteractionAllowed(Boolean *state) 873 { 874 BEGIN_SECAPI 875 876 Required(state)=globals().getUserInteractionAllowed(); 877 878 END_SECAPI 879 } 880 881 882 OSStatus 883 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle) 884 { 885 BEGIN_SECAPI 886 887 os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 888 os_activity_scope(activity); 889 os_release(activity); 890 891 RequiredParam(dldbHandle); 892 893 Keychain keychain = Keychain::optional(keychainRef); 894 *dldbHandle = keychain->database()->handle(); 895 896 END_SECAPI 897 } 898 899 static ModuleNexus<Mutex> gSecReturnedKeychainCSPsMutex; 900 static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeychainCSPs; 901 902 OSStatus 903 SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle) 904 { 905 BEGIN_SECAPI 906 907 RequiredParam(cspHandle); 908 909 Keychain keychain = Keychain::optional(keychainRef); 910 911 // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP). 912 // Keep a global pointer to it to force the CSP to stay live forever. 913 CssmClient::CSP returnedKeychainCSP = keychain->csp(); 914 { 915 StLock<Mutex> _(gSecReturnedKeychainCSPsMutex()); 916 gSecReturnedKeychainCSPs().insert(returnedKeychainCSP); 917 } 918 *cspHandle = returnedKeychainCSP->handle(); 919 920 END_SECAPI 921 } 922 923 924 OSStatus 925 SecKeychainCopyAccess(SecKeychainRef keychainRef, SecAccessRef *accessRef) 926 { 927 BEGIN_SECAPI 928 929 MacOSError::throwMe(errSecUnimplemented);//%%%for now 930 931 END_SECAPI 932 } 933 934 935 OSStatus 936 SecKeychainSetAccess(SecKeychainRef keychainRef, SecAccessRef accessRef) 937 { 938 BEGIN_SECAPI 939 940 MacOSError::throwMe(errSecUnimplemented);//%%%for now 941 942 END_SECAPI 943 } 944 945 946 #pragma mark ---- Private API ---- 947 948 949 OSStatus 950 SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) 951 { 952 BEGIN_SECAPI 953 954 os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 955 os_activity_scope(activity); 956 os_release(activity); 957 958 Keychain keychain = Keychain::optional(keychainRef); 959 keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword); 960 961 END_SECAPI 962 } 963 964 965 OSStatus 966 SecKeychainCopyLogin(SecKeychainRef *keychainRef) 967 { 968 BEGIN_SECAPI 969 970 os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 971 os_activity_scope(activity); 972 os_release(activity); 973 974 RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle(); 975 976 END_SECAPI 977 } 978 979 980 OSStatus 981 SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password) 982 { 983 BEGIN_SECAPI 984 985 os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 986 os_activity_scope(activity); 987 os_release(activity); 988 989 try 990 { 991 if (password) { 992 globals().storageManager.login(nameLength, name, passwordLength, password, false); 993 } else { 994 globals().storageManager.stashLogin(); 995 } 996 } 997 catch (CommonError &e) 998 { 999 secnotice("KCLogin", "SecKeychainLogin failed: %d, password was%s supplied", (int)e.osStatus(), password?"":" not"); 1000 if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED) 1001 { 1002 return errSecAuthFailed; 1003 } 1004 else 1005 { 1006 return e.osStatus(); 1007 } 1008 } 1009 1010 catch (...) { 1011 __secapiresult=errSecInternalComponent; 1012 } 1013 secnotice("KCLogin", "SecKeychainLogin result: %d, password was%s supplied", (int)__secapiresult, password?"":" not"); 1014 1015 END_SECAPI 1016 } 1017 1018 OSStatus SecKeychainStash() 1019 { 1020 BEGIN_SECAPI 1021 1022 os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1023 os_activity_scope(activity); 1024 os_release(activity); 1025 1026 try 1027 { 1028 globals().storageManager.stashKeychain(); 1029 } 1030 catch (CommonError &e) 1031 { 1032 if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED) 1033 { 1034 return errSecAuthFailed; 1035 } 1036 else 1037 { 1038 return e.osStatus(); 1039 } 1040 } 1041 1042 END_SECAPI 1043 } 1044 1045 OSStatus 1046 SecKeychainLogout() 1047 { 1048 BEGIN_SECAPI 1049 1050 os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1051 os_activity_scope(activity); 1052 os_release(activity); 1053 1054 globals().storageManager.logout(); 1055 1056 END_SECAPI 1057 } 1058 1059 /* (non-exported C utility routine) 'Makes' a keychain based on a full path 1060 */ 1061 static Keychain make(const char *name) 1062 { 1063 return globals().storageManager.make(name); 1064 } 1065 1066 /* 'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs. 1067 Note this version doesn't take an accessRef or password. 1068 The "KC" create API takes a keychainRef... 1069 */ 1070 OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef) 1071 { 1072 BEGIN_SECAPI 1073 1074 RequiredParam(fullPathName); 1075 RequiredParam(keychainRef)=make(fullPathName)->handle(); 1076 END_SECAPI 1077 } 1078 1079 1080 /* Determines if the keychainRef is a valid keychain. 1081 */ 1082 OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) 1083 { 1084 BEGIN_SECAPI 1085 1086 *isValid = false; 1087 if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL) 1088 *isValid = true; 1089 END_SECAPI 1090 } 1091 1092 /* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs. 1093 */ 1094 OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) 1095 { 1096 BEGIN_SECAPI 1097 1098 os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1099 os_activity_scope(activity); 1100 os_release(activity); 1101 StorageManager::KeychainList singleton; 1102 singleton.push_back(KeychainImpl::required(keychainRef)); 1103 globals().storageManager.remove(singleton); 1104 END_SECAPI 1105 } 1106 1107 /* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs. 1108 */ 1109 OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword) 1110 { 1111 BEGIN_SECAPI 1112 1113 os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1114 os_activity_scope(activity); 1115 os_release(activity); 1116 RequiredParam(inPassword); 1117 KeychainImpl::required(keychainRef)->create(passwordLength, inPassword); 1118 END_SECAPI 1119 } 1120 1121 /* Modify a keychain so that it can be synchronized. 1122 */ 1123 OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData) 1124 { 1125 BEGIN_SECAPI 1126 1127 os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1128 os_activity_scope(activity); 1129 os_release(activity); 1130 1131 // do error checking for required parameters 1132 RequiredParam(dbBlobArray); 1133 RequiredParam(extraData); 1134 1135 const CssmData extraCssmData(const_cast<UInt8 *>(CFDataGetBytePtr(extraData)), 1136 CFDataGetLength(extraData)); 1137 1138 CFIndex dbBlobArrayCount = CFArrayGetCount(dbBlobArray); 1139 size_t space = sizeof(uint8) + (dbBlobArrayCount * sizeof(SecurityServer::DbHandle)); 1140 void *dataPtr = (void*)malloc(space); 1141 if ( !dataPtr ) 1142 return errSecAllocate; 1143 // 1144 // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with. 1145 // 1146 uint8* sizePtr = (uint8*)dataPtr; 1147 *sizePtr = dbBlobArrayCount; 1148 SecurityServer::DbHandle *currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1); 1149 CFIndex index; 1150 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard()); 1151 for (index=0; index < dbBlobArrayCount; index++) 1152 { 1153 CFDataRef cfBlobData = (CFDataRef)CFArrayGetValueAtIndex(dbBlobArray, index); 1154 const CssmData thisKCData(const_cast<UInt8 *>(CFDataGetBytePtr(cfBlobData)), CFDataGetLength(cfBlobData)); 1155 // 1156 // Since it's to a DbHandle that's not on our disk (it came from user's iDisk), 1157 // it's OK to use the mIdentifier and access credentials of the keychain we're recoding. 1158 // 1159 Keychain kc = KeychainImpl::required(keychainRef); 1160 *currDbHandle = ss.decodeDb(kc->dlDbIdentifier(), kc->defaultCredentials(), thisKCData); /* returns a DbHandle (IPCDbHandle) */ 1161 1162 currDbHandle++; 1163 } 1164 // do the work 1165 Keychain keychain = Keychain::optional(keychainRef); 1166 const CssmData data(const_cast<UInt8 *>((uint8*)dataPtr), space); 1167 Boolean recodeFailed = false; 1168 1169 int errCode=errSecSuccess; 1170 1171 try 1172 { 1173 keychain->recode(data, extraCssmData); 1174 } 1175 catch (MacOSError e) 1176 { 1177 errCode = e.osStatus(); 1178 recodeFailed = true; 1179 } 1180 catch (UnixError ue) 1181 { 1182 errCode = ue.unixError(); 1183 } 1184 1185 currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1); 1186 for (index=0; index < dbBlobArrayCount; index++) 1187 { 1188 ss.releaseDb(*currDbHandle); 1189 currDbHandle++; 1190 } 1191 if ( dataPtr ) 1192 free(dataPtr); 1193 1194 if ( recodeFailed ) 1195 { 1196 return errCode; 1197 } 1198 1199 END_SECAPI 1200 } 1201 1202 OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature) 1203 { 1204 BEGIN_SECAPI 1205 1206 os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1207 os_activity_scope(activity); 1208 os_release(activity); 1209 1210 // do error checking for required parameters 1211 RequiredParam(keychainSignature); 1212 1213 // make a keychain object "wrapper" for this keychain ref 1214 Keychain keychain = Keychain::optional(keychainRef); 1215 CssmAutoData data(keychain->database()->allocator()); 1216 keychain->copyBlob(data.get()); 1217 1218 // get the cssmDBBlob 1219 const SecurityServer::DbBlob *cssmDBBlob = 1220 data.get().interpretedAs<const SecurityServer::DbBlob>(); 1221 1222 // convert from CDSA standards to CF standards 1223 *keychainSignature = CFDataCreate(kCFAllocatorDefault, 1224 cssmDBBlob->randomSignature.bytes, 1225 sizeof(SecurityServer::DbBlob::Signature)); 1226 1227 END_SECAPI 1228 } 1229 1230 OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) 1231 { 1232 BEGIN_SECAPI 1233 1234 os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1235 os_activity_scope(activity); 1236 os_release(activity); 1237 1238 // do error checking for required parameters 1239 RequiredParam(dbBlob); 1240 1241 // make a keychain object "wrapper" for this keychain ref 1242 Keychain keychain = Keychain::optional(keychainRef); 1243 CssmAutoData data(keychain->database()->allocator()); 1244 keychain->copyBlob(data.get()); 1245 1246 // convert from CDSA standards to CF standards 1247 *dbBlob = CFDataCreate(kCFAllocatorDefault, data, data.length()); 1248 1249 END_SECAPI 1250 } 1251 1252 // make a new keychain with pre-existing secrets 1253 OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef) 1254 { 1255 BEGIN_SECAPI 1256 1257 os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1258 os_activity_scope(activity); 1259 os_release(activity); 1260 1261 KCThrowParamErrIf_(!fullPathName); 1262 KCThrowParamErrIf_(!dbBlob); 1263 1264 Keychain keychain = globals().storageManager.make(fullPathName); 1265 1266 CssmData blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob)), CFDataGetLength(dbBlob)); 1267 1268 // @@@ the call to StorageManager::make above leaves keychain the the cache. 1269 // If the create below fails we should probably remove it. 1270 keychain->createWithBlob(blob); 1271 1272 RequiredParam(kcRef)=keychain->handle(); 1273 1274 // 1275 1276 END_SECAPI 1277 } 1278 1279 // add a non-file based DB to the keychain list 1280 OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, 1281 const CSSM_GUID *guid, uint32 subServiceType) 1282 { 1283 BEGIN_SECAPI 1284 1285 os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1286 os_activity_scope(activity); 1287 os_release(activity); 1288 1289 RequiredParam(dbName); 1290 StorageManager &smr = globals().storageManager; 1291 smr.addToDomainList(domain, dbName, *guid, subServiceType); 1292 1293 END_SECAPI 1294 } 1295 1296 // determine if a non-file based DB is in the keychain list 1297 OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, 1298 const CSSM_GUID *guid, uint32 subServiceType) 1299 { 1300 BEGIN_SECAPI 1301 1302 RequiredParam(dbName); 1303 StorageManager &smr = globals().storageManager; 1304 smr.isInDomainList(domain, dbName, *guid, subServiceType); 1305 END_SECAPI 1306 } 1307 1308 // remove a non-file based DB from the keychain list 1309 OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, 1310 const CSSM_GUID *guid, uint32 subServiceType) 1311 { 1312 BEGIN_SECAPI 1313 1314 os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1315 os_activity_scope(activity); 1316 os_release(activity); 1317 RequiredParam(dbName); 1318 StorageManager &smr = globals().storageManager; 1319 smr.removeFromDomainList(domain, dbName, *guid, subServiceType); 1320 END_SECAPI 1321 } 1322 1323 1324 // set server mode -- must be called before any other Sec* etc. call 1325 void SecKeychainSetServerMode() 1326 { 1327 gServerMode = true; 1328 } 1329 1330 1331 1332 OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) 1333 { 1334 BEGIN_SECAPI 1335 1336 os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1337 os_activity_scope(activity); 1338 os_release(activity); 1339 RequiredParam(kcRef); 1340 Keychain keychain = Keychain::optional(kcRef); 1341 keychain->setBatchMode(mode, rollback); 1342 END_SECAPI 1343 } 1344 1345 1346 1347 OSStatus SecKeychainCleanupHandles() 1348 { 1349 BEGIN_SECAPI 1350 1351 END_SECAPI // which causes the handle cache cleanup routine to run 1352 } 1353 1354 OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) 1355 { 1356 BEGIN_SECAPI 1357 1358 os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1359 os_activity_scope(activity); 1360 os_release(activity); 1361 SecurityServer::ClientSession().verifyKeyStorePassphrase(retries); 1362 END_SECAPI 1363 } 1364 1365 OSStatus SecKeychainChangeKeyStorePassphrase() 1366 { 1367 BEGIN_SECAPI 1368 1369 os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1370 os_activity_scope(activity); 1371 os_release(activity); 1372 SecurityServer::ClientSession().changeKeyStorePassphrase(); 1373 END_SECAPI 1374 } 1375 1376 static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRef *masterKey, CFStringRef password) 1377 { 1378 BEGIN_SECAPI 1379 1380 os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1381 os_activity_scope(activity); 1382 os_release(activity); 1383 1384 // make a keychain object "wrapper" for this keychain ref 1385 Keychain keychain = Keychain::optional(userKeychainRef); 1386 1387 CssmClient::Db db = keychain->database(); 1388 1389 // create the keychain, using appropriate credentials 1390 Allocator &alloc = db->allocator(); 1391 AutoCredentials cred(alloc); // will leak, but we're quitting soon :-) 1392 1393 char passphrase[1024]; 1394 CFStringGetCString(password, passphrase, sizeof(passphrase), kCFStringEncodingUTF8); 1395 1396 // use this passphrase 1397 cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, 1398 new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), 1399 new(alloc) ListElement(StringData(passphrase))); 1400 db->authenticate(CSSM_DB_ACCESS_READ, &cred); 1401 1402 CSSM_DL_DB_HANDLE dlDb = db->handle(); 1403 CssmData dlDbData = CssmData::wrap(dlDb); 1404 CssmKey refKey; 1405 KeySpec spec(CSSM_KEYUSE_ANY, 1406 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE); 1407 1408 DeriveKey derive(keychain->csp(), CSSM_ALGID_KEYCHAIN_KEY, CSSM_ALGID_3DES_3KEY, 3 * 64); 1409 derive(&dlDbData, spec, refKey); 1410 1411 // now extract the raw keybits 1412 CssmKey rawKey; 1413 WrapKey wrap(keychain->csp(), CSSM_ALGID_NONE); 1414 wrap(refKey, rawKey); 1415 1416 *masterKey = CFDataCreate(kCFAllocatorDefault, rawKey.keyData(), rawKey.length()); 1417 1418 END_SECAPI 1419 } 1420 1421 static const char *kAutologinPWFilePath = "/etc/kcpassword"; 1422 static const uint32_t kObfuscatedPasswordSizeMultiple = 12; 1423 static const uint32_t buffer_size = 512; 1424 static const uint8_t kObfuscationKey[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f}; 1425 1426 static void obfuscate(void *buffer, size_t bufferLength) 1427 { 1428 uint8_t *pBuf = (uint8_t *) buffer; 1429 const uint8_t *pKey = kObfuscationKey, *eKey = pKey + sizeof( kObfuscationKey ); 1430 1431 while (bufferLength--) { 1432 *pBuf = *pBuf ^ *pKey; 1433 ++pKey; 1434 ++pBuf; 1435 if (pKey == eKey) 1436 pKey = kObfuscationKey; 1437 } 1438 } 1439 1440 static bool _SASetAutologinPW(CFStringRef inAutologinPW) 1441 { 1442 bool result = false; 1443 struct stat sb; 1444 1445 // Delete the kcpassword file if it exists already 1446 if (stat(kAutologinPWFilePath, &sb) == 0) 1447 unlink( kAutologinPWFilePath ); 1448 1449 // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off. 1450 if (inAutologinPW != NULL) { 1451 char buffer[buffer_size]; 1452 const char *pwAsUTF8String = CFStringGetCStringPtr(inAutologinPW, kCFStringEncodingUTF8); 1453 if (pwAsUTF8String == NULL) { 1454 if (CFStringGetCString(inAutologinPW, buffer, buffer_size, kCFStringEncodingUTF8)) pwAsUTF8String = buffer; 1455 } 1456 1457 if (pwAsUTF8String != NULL) { 1458 size_t pwLength = strlen(pwAsUTF8String) + 1; 1459 size_t obfuscatedPWLength; 1460 char *obfuscatedPWBuffer; 1461 1462 // The size of the obfuscated password should be the smallest multiple of 1463 // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength. 1464 obfuscatedPWLength = (((pwLength - 1) / kObfuscatedPasswordSizeMultiple) + 1) * kObfuscatedPasswordSizeMultiple; 1465 obfuscatedPWBuffer = (char *) malloc(obfuscatedPWLength); 1466 1467 // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer 1468 bcopy(pwAsUTF8String, obfuscatedPWBuffer, pwLength); 1469 1470 // Pad remainder of obfuscatedPWBuffer with random bytes 1471 { 1472 char *p; 1473 char *endOfBuffer = obfuscatedPWBuffer + obfuscatedPWLength; 1474 1475 for (p = obfuscatedPWBuffer + pwLength; p < endOfBuffer; ++p) 1476 *p = random() & 0x000000FF; 1477 } 1478 1479 obfuscate(obfuscatedPWBuffer, obfuscatedPWLength); 1480 1481 int pwFile = open(kAutologinPWFilePath, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR); 1482 if (pwFile >= 0) { 1483 size_t wrote = write(pwFile, obfuscatedPWBuffer, obfuscatedPWLength); 1484 if (wrote == obfuscatedPWLength) 1485 result = true; 1486 close(pwFile); 1487 } 1488 1489 chmod(kAutologinPWFilePath, S_IRUSR | S_IWUSR); 1490 free(obfuscatedPWBuffer); 1491 } 1492 } 1493 1494 return result; 1495 } 1496 1497 OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) { 1498 COUNTLEGACYAPI 1499 SecTrustedApplicationRef itemPath; 1500 SecAccessRef ourAccessRef = NULL; 1501 1502 OSStatus result = errSecParam; 1503 1504 if (userKeychainRef == NULL) { 1505 // We don't have a specific user keychain, fall back 1506 if (_SASetAutologinPW(password)) 1507 result = errSecSuccess; 1508 1509 return result; 1510 } 1511 1512 CFDataRef masterKey = NULL; 1513 result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password); 1514 if (errSecSuccess != result) { 1515 return result; 1516 } 1517 1518 result = SecKeychainStash(); 1519 if (errSecSuccess != result) { 1520 if (masterKey != NULL) CFRelease(masterKey); 1521 return result; 1522 } 1523 1524 CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 1525 if (noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath) 1526 CFArrayAppendValue(trustedApplications, itemPath); 1527 1528 if (trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) { 1529 if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) { 1530 SecKeychainRef internalSystemKeychainRef = NULL; 1531 if (NULL == systemKeychainRef) { 1532 SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &internalSystemKeychainRef); 1533 } else { 1534 internalSystemKeychainRef = systemKeychainRef; 1535 } 1536 1537 const void *queryKeys[] = { kSecClass, 1538 kSecAttrService, 1539 kSecAttrAccount, 1540 kSecUseKeychain, 1541 }; 1542 const void *queryValues[] = { kSecClassGenericPassword, 1543 CFSTR("com.apple.loginwindow.auto-login"), 1544 username, 1545 internalSystemKeychainRef, 1546 }; 1547 1548 const void *updateKeys[] = { kSecAttrAccess, 1549 kSecValueData, 1550 }; 1551 const void *updateValues[] = { ourAccessRef, 1552 masterKey, 1553 }; 1554 1555 CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, queryKeys, queryValues, sizeof(queryValues)/sizeof(*queryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1556 CFDictionaryRef update = CFDictionaryCreate(kCFAllocatorDefault, updateKeys, updateValues, sizeof(updateValues)/sizeof(*updateValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1557 1558 result = SecItemUpdate(query, update); 1559 1560 if (errSecSuccess != result) { 1561 const void *addKeys[] = { kSecClass, 1562 kSecAttrService, 1563 kSecAttrAccount, 1564 kSecUseKeychain, 1565 kSecAttrAccess, 1566 kSecValueData, 1567 }; 1568 const void *addValues[] = { kSecClassGenericPassword, 1569 CFSTR("com.apple.loginwindow.auto-login"), 1570 username, 1571 internalSystemKeychainRef, 1572 ourAccessRef, 1573 masterKey, 1574 }; 1575 1576 CFDictionaryRef add = CFDictionaryCreate(kCFAllocatorDefault, addKeys, addValues, sizeof(addValues)/sizeof(*addValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1577 result = SecItemAdd(add, NULL); 1578 if (NULL != add) CFRelease(add); 1579 } 1580 1581 if (NULL != query) CFRelease(query); 1582 if (NULL != update) CFRelease(update); 1583 1584 // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one 1585 if (systemKeychainRef == NULL) CFRelease(internalSystemKeychainRef); 1586 } 1587 } 1588 1589 if (NULL != masterKey) CFRelease(masterKey); 1590 if (NULL != trustedApplications) CFRelease(trustedApplications); 1591 if (NULL != ourAccessRef) CFRelease(ourAccessRef); 1592 1593 return result; 1594 } 1595 1596 OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) 1597 { 1598 BEGIN_SECAPI 1599 1600 os_activity_t activity = os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); 1601 os_activity_scope(activity); 1602 os_release(activity); 1603 1604 if(attempts) { 1605 SecurityServer::ClientSession().getUserPromptAttempts(*attempts); 1606 } 1607 1608 END_SECAPI 1609 } 1610 1611 OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash, 1612 SecKeychainRef userKeychain, CFStringRef password) 1613 { 1614 COUNTLEGACYAPI 1615 CFRef<CFStringRef> pwd; 1616 OSStatus result; 1617 1618 if (password == NULL || CFStringGetLength(password) == 0) { 1619 AuthorizationRef authorizationRef; 1620 result = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorizationRef); 1621 if (result != errAuthorizationSuccess) { 1622 secnotice("SecKeychain", "failed to create authorization"); 1623 return result; 1624 } 1625 1626 AuthorizationItem myItems = {"com.apple.ctk.pair", 0, NULL, 0}; 1627 AuthorizationRights myRights = {1, &myItems}; 1628 1629 char pathName[PATH_MAX]; 1630 UInt32 pathLength = PATH_MAX; 1631 result = SecKeychainGetPath(userKeychain, &pathLength, pathName); 1632 if (result != errSecSuccess) { 1633 secnotice("SecKeychain", "failed to create authorization"); 1634 return result; 1635 } 1636 1637 Boolean checkPwd = TRUE; 1638 Boolean ignoreSession = TRUE; 1639 AuthorizationItem envItems[] = { 1640 {AGENT_HINT_KEYCHAIN_PATH, pathLength, pathName, 0}, 1641 {AGENT_HINT_KEYCHAIN_CHECK, sizeof(checkPwd), &checkPwd}, 1642 {AGENT_HINT_IGNORE_SESSION, sizeof(ignoreSession), &ignoreSession} 1643 }; 1644 1645 AuthorizationEnvironment environment = {3, envItems}; 1646 AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; 1647 result = AuthorizationCopyRights(authorizationRef, &myRights, &environment, flags, NULL); 1648 secnotice("SecKeychain", "Authorization result: %d", (int)result); 1649 1650 if (result == errAuthorizationSuccess) { 1651 AuthorizationItemSet *items; 1652 result = AuthorizationCopyInfo(authorizationRef, kAuthorizationEnvironmentPassword, &items); 1653 secnotice("SecKeychain", "Items copy result: %d", (int)result); 1654 if (result == errAuthorizationSuccess) { 1655 secnotice("SecKeychain", "Items count: %d", items->count); 1656 if (items->count > 0) { 1657 pwd = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)items->items[0].value, kCFStringEncodingUTF8); 1658 if (pwd) { 1659 secnotice("SecKeychain", "Got kcpass"); 1660 } 1661 } 1662 AuthorizationFreeItemSet(items); 1663 } 1664 } 1665 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); 1666 if (result != errAuthorizationSuccess) { 1667 secnotice("SecKeychain", "did not get authorization to pair the card"); 1668 return result; 1669 } 1670 } else { 1671 pwd.take(password); 1672 } 1673 1674 if (!pwd) { 1675 secnotice("SecKeychain", "did not get kcpass"); 1676 return errSecInternalComponent; 1677 } 1678 1679 CFRef<CFDataRef> masterKey; 1680 result = SecKeychainGetMasterKey(userKeychain, masterKey.take(), pwd); 1681 if (result != errSecSuccess) { 1682 secnotice("SecKeychain", "Failed to get master key: %d", (int) result); 1683 return result; 1684 } 1685 1686 CFRef<CFDataRef> scBlob; 1687 result = TokenLoginGetScBlob(wrapPubKeyHash, tokenID, pwd, scBlob.take()); 1688 if (result != errSecSuccess) { 1689 secnotice("SecKeychain", "Failed to get stash: %d", (int) result); 1690 return result; 1691 } 1692 1693 result = TokenLoginCreateLoginData(tokenID, pubKeyHash, wrapPubKeyHash, masterKey, scBlob); 1694 if (result != errSecSuccess) { 1695 secnotice("SecKeychain", "Failed to create login data: %d", (int) result); 1696 return result; 1697 } 1698 1699 secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result); 1700 1701 // create SC KEK 1702 // this might fail if KC password is different from user's password 1703 uid_t uid = geteuid(); 1704 if (!uid) { 1705 uid = getuid(); 1706 } 1707 struct passwd *passwd = getpwuid(uid); 1708 if (passwd) { 1709 CFRef<CFStringRef> username = CFStringCreateWithCString(kCFAllocatorDefault, passwd->pw_name, kCFStringEncodingUTF8); 1710 OSStatus kekRes = TKAddSecureToken(username, pwd, tokenID, wrapPubKeyHash); 1711 if (kekRes != noErr) { 1712 secnotice("SecKeychain", "Failed to register SC token: %d", (int) kekRes); // do not fail because KC functionality be still OK 1713 } 1714 } else { 1715 secnotice("SecKeychain", "Unable to get name for uid %d", uid); 1716 } 1717 return result; 1718 } 1719 1720 OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash) 1721 { 1722 COUNTLEGACYAPI 1723 OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash); 1724 if (result != errSecSuccess) { 1725 secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result); 1726 } 1727 return result; 1728 }