1/* 2 * Copyright (c) 2000-2004 Apple Computer, 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_keychain/KCExceptions.h> 29#include <securityd_client/ssblob.h> 30#include "SecBridge.h" 31#include "CCallbackMgr.h" 32#include <security_cdsa_utilities/Schema.h> 33#include <pwd.h> 34 35CFTypeID 36SecKeychainGetTypeID(void) 37{ 38 BEGIN_SECAPI 39 40 return gTypes().KeychainImpl.typeID; 41 42 END_SECAPI1(_kCFRuntimeNotATypeID) 43} 44 45 46OSStatus 47SecKeychainGetVersion(UInt32 *returnVers) 48{ 49 if (!returnVers) 50 return errSecSuccess; 51 52 *returnVers = 0x02028000; 53 return errSecSuccess; 54} 55 56 57OSStatus 58SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef) 59{ 60 BEGIN_SECAPI 61 62 RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle(); 63 64 END_SECAPI 65} 66 67 68OSStatus 69SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, 70 const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) 71{ 72 BEGIN_SECAPI 73 74 // range check parameters 75 RequiredParam (guid); 76 RequiredParam (dbName); 77 78 // create a DLDbIdentifier that describes what should be opened 79 const CSSM_VERSION *version = NULL; 80 const CssmSubserviceUid ssuid(*guid, version, subserviceId, subserviceType); 81 DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation); 82 83 // make a keychain from the supplied info 84 RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false)->handle (); 85 86 END_SECAPI 87} 88 89 90OSStatus 91SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password, 92 Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef) 93{ 94 BEGIN_SECAPI 95 96 KCThrowParamErrIf_(!pathName); 97 Keychain keychain = globals().storageManager.make(pathName); 98 99 // @@@ the call to StorageManager::make above leaves keychain the the cache. 100 // If the create below fails we should probably remove it. 101 if(promptUser) 102 keychain->create(); 103 else 104 { 105 KCThrowParamErrIf_(!password); 106 keychain->create(passwordLength, password); 107 } 108 109 RequiredParam(keychainRef)=keychain->handle(); 110 111 END_SECAPI 112} 113 114 115OSStatus 116SecKeychainDelete(SecKeychainRef keychainOrArray) 117{ 118 BEGIN_SECAPI 119 120 KCThrowIf_(!keychainOrArray, errSecInvalidKeychain); 121 StorageManager::KeychainList keychains; 122 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 123 124 globals().storageManager.remove(keychains, true); 125 126 END_SECAPI 127} 128 129 130OSStatus 131SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings) 132{ 133 BEGIN_SECAPI 134 135 Keychain keychain = Keychain::optional(keychainRef); 136 if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1) 137 { 138 UInt32 lockInterval=newSettings->lockInterval; 139 bool lockOnSleep=newSettings->lockOnSleep; 140 keychain->setSettings(lockInterval, lockOnSleep); 141 } 142 143 END_SECAPI 144} 145 146 147OSStatus 148SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings) 149{ 150 BEGIN_SECAPI 151 152 Keychain keychain = Keychain::optional(keychainRef); 153 if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1) 154 { 155 uint32 lockInterval; 156 bool lockOnSleep; 157 158 keychain->getSettings(lockInterval, lockOnSleep); 159 outSettings->lockInterval=lockInterval; 160 outSettings->lockOnSleep=lockOnSleep; 161 } 162 163 END_SECAPI 164} 165 166 167OSStatus 168SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void *password, Boolean usePassword) 169{ 170 BEGIN_SECAPI 171 172 Keychain keychain = Keychain::optional(keychainRef); 173 174 if (usePassword) 175 keychain->unlock(CssmData(const_cast<void *>(password), passwordLength)); 176 else 177 keychain->unlock(); 178 179 END_SECAPI 180} 181 182 183OSStatus 184SecKeychainLock(SecKeychainRef keychainRef) 185{ 186 BEGIN_SECAPI 187 188 Keychain keychain = Keychain::optional(keychainRef); 189 keychain->lock(); 190 191 END_SECAPI 192} 193 194 195OSStatus 196SecKeychainLockAll(void) 197{ 198 BEGIN_SECAPI 199 200 globals().storageManager.lockAll(); 201 202 END_SECAPI 203} 204 205 206OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList) 207{ 208 BEGIN_SECAPI 209 // 210 // Get the current user (using fallback method if necessary) 211 // 212 char* uName = getenv("USER"); 213 string userName = uName ? uName : ""; 214 if ( userName.length() == 0 ) 215 { 216 uid_t uid = geteuid(); 217 if (!uid) uid = getuid(); 218 struct passwd *pw = getpwuid(uid); // fallback case... 219 if (pw) 220 userName = pw->pw_name; 221 endpwent(); 222 } 223 if ( userName.length() == 0 ) // did we ultimately get one? 224 MacOSError::throwMe(errAuthorizationInternal); 225 226 if (password) 227 { 228 // Clear the plist and move aside (rename) the existing login.keychain 229 globals().storageManager.resetKeychain(resetSearchList); 230 231 // Create the login keychain without UI 232 globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password); 233 234 // Set it as the default 235 Keychain keychain = globals().storageManager.loginKeychain(); 236 globals().storageManager.defaultKeychain(keychain); 237 } 238 else 239 { 240 // Create the login keychain, prompting for password 241 // (implicitly calls resetKeychain, login, and defaultKeychain) 242 globals().storageManager.makeLoginAuthUI(NULL); 243 } 244 245 SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData()); 246 247 // Post a "list changed" event after a reset, so apps can refresh their list. 248 // Make sure we are not holding mLock when we post this event. 249 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent); 250 251 END_SECAPI 252} 253 254OSStatus 255SecKeychainCopyDefault(SecKeychainRef *keychainRef) 256{ 257 BEGIN_SECAPI 258 259 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain()->handle(); 260 261 END_SECAPI 262} 263 264 265OSStatus 266SecKeychainSetDefault(SecKeychainRef keychainRef) 267{ 268 BEGIN_SECAPI 269 270 globals().storageManager.defaultKeychain(Keychain::optional(keychainRef)); 271 272 END_SECAPI 273} 274 275OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) 276{ 277 BEGIN_SECAPI 278 279 RequiredParam(searchList); 280 StorageManager &smr = globals().storageManager; 281 StorageManager::KeychainList keychainList; 282 smr.getSearchList(keychainList); 283 *searchList = smr.convertFromKeychainList(keychainList); 284 285 END_SECAPI 286} 287 288OSStatus SecKeychainSetSearchList(CFArrayRef searchList) 289{ 290 BEGIN_SECAPI 291 292 RequiredParam(searchList); 293 StorageManager &smr = globals().storageManager; 294 StorageManager::KeychainList keychainList; 295 smr.convertToKeychainList(searchList, keychainList); 296 smr.setSearchList(keychainList); 297 298 END_SECAPI 299} 300 301OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef) 302{ 303 BEGIN_SECAPI 304 305 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle(); 306 307 END_SECAPI 308} 309 310OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef) 311{ 312 BEGIN_SECAPI 313 314 globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef)); 315 316 END_SECAPI 317} 318 319OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef *searchList) 320{ 321 BEGIN_SECAPI 322 323 RequiredParam(searchList); 324 StorageManager &smr = globals().storageManager; 325 StorageManager::KeychainList keychainList; 326 smr.getSearchList(domain, keychainList); 327 *searchList = smr.convertFromKeychainList(keychainList); 328 329 END_SECAPI 330} 331 332OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList) 333{ 334 BEGIN_SECAPI 335 336 RequiredParam(searchList); 337 StorageManager &smr = globals().storageManager; 338 StorageManager::KeychainList keychainList; 339 smr.convertToKeychainList(searchList, keychainList); 340 smr.setSearchList(domain, keychainList); 341 342 END_SECAPI 343} 344 345OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) 346{ 347 BEGIN_SECAPI 348 349 globals().storageManager.domain(domain); 350 351 END_SECAPI 352} 353 354OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain) 355{ 356 BEGIN_SECAPI 357 358 *domain = globals().storageManager.domain(); 359 360 END_SECAPI 361} 362 363 364OSStatus 365SecKeychainGetStatus(SecKeychainRef keychainRef, SecKeychainStatus *keychainStatus) 366{ 367 BEGIN_SECAPI 368 369 RequiredParam(keychainStatus) = (SecKeychainStatus)Keychain::optional(keychainRef)->status(); 370 371 END_SECAPI 372} 373 374 375OSStatus 376SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathName) 377{ 378 BEGIN_SECAPI 379 380 RequiredParam(pathName); 381 RequiredParam(ioPathLength); 382 383 const char *name = Keychain::optional(keychainRef)->name(); 384 UInt32 nameLen = (UInt32)strlen(name); 385 UInt32 callersLen = *ioPathLength; 386 *ioPathLength = nameLen; 387 if (nameLen+1 > callersLen) // if the client's buffer is too small (including null-termination), throw 388 return errSecBufferTooSmall; 389 strncpy(pathName, name, nameLen); 390 pathName[nameLen] = 0; 391 *ioPathLength = nameLen; // set the length. 392 393 END_SECAPI 394} 395 396 397// @@@ Deprecated 398UInt16 399SecKeychainListGetCount(void) 400{ 401 BEGIN_SECAPI 402 403 return globals().storageManager.size(); 404 405 END_SECAPI1(0) 406} 407 408 409// @@@ Deprecated 410OSStatus 411SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef) 412{ 413 BEGIN_SECAPI 414 415 KeychainCore::StorageManager &smgr=KeychainCore::globals().storageManager; 416 RequiredParam(keychainRef)=smgr[index]->handle(); 417 418 END_SECAPI 419} 420 421 422// @@@ Deprecated 423OSStatus 424SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef) 425{ 426 BEGIN_SECAPI 427 428 Required(keychainRef); 429 Keychain keychain = Keychain::optional(*keychainRef); 430 StorageManager::KeychainList keychainList; 431 keychainList.push_back(keychain); 432 globals().storageManager.remove(keychainList); 433 *keychainRef = NULL; 434 435 END_SECAPI 436} 437 438 439OSStatus 440SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef, UInt32 itemID, SecKeychainAttributeInfo **info) 441{ 442 BEGIN_SECAPI 443 444 Keychain keychain = Keychain::optional(keychainRef); 445 keychain->getAttributeInfoForItemID(itemID, info); 446 447 END_SECAPI 448} 449 450 451OSStatus 452SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) 453{ 454 BEGIN_SECAPI 455 456 KeychainImpl::freeAttributeInfo(info); 457 458 END_SECAPI 459} 460 461 462pascal OSStatus 463SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext) 464{ 465 BEGIN_SECAPI 466 467 RequiredParam(callbackFunction); 468 CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext); 469 470 END_SECAPI 471} 472 473 474OSStatus 475SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) 476{ 477 BEGIN_SECAPI 478 479 RequiredParam(callbackFunction); 480 CCallbackMgr::RemoveCallback(callbackFunction); 481 482 END_SECAPI 483} 484 485OSStatus 486SecKeychainAddInternetPassword(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) 487{ 488 BEGIN_SECAPI 489 490 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL); 491 // @@@ Get real itemClass 492 Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false); 493 494 if (serverName && serverNameLength) 495 { 496 CssmData server(const_cast<void *>(reinterpret_cast<const void *>(serverName)), serverNameLength); 497 item->setAttribute(Schema::attributeInfo(kSecServerItemAttr), server); 498 // use server name as default label 499 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), server); 500 } 501 502 if (accountName && accountNameLength) 503 { 504 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength); 505 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); 506 } 507 508 if (securityDomain && securityDomainLength) 509 item->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr), 510 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain)), securityDomainLength)); 511 512 item->setAttribute(Schema::attributeInfo(kSecPortItemAttr), UInt32(port)); 513 item->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr), protocol); 514 item->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr), authenticationType); 515 516 if (path && pathLength) 517 item->setAttribute(Schema::attributeInfo(kSecPathItemAttr), 518 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path)), pathLength)); 519 520 Keychain keychain = nil; 521 try 522 { 523 keychain = Keychain::optional(keychainRef); 524 if ( !keychain->exists() ) 525 { 526 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. 527 } 528 } 529 catch(...) 530 { 531 keychain = globals().storageManager.defaultKeychainUI(item); 532 } 533 534 keychain->add(item); 535 536 if (itemRef) 537 *itemRef = item->handle(); 538 539 END_SECAPI 540} 541 542 543OSStatus 544SecKeychainFindInternetPassword(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) 545 546{ 547 BEGIN_SECAPI 548 549 StorageManager::KeychainList keychains; 550 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 551 KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL); 552 553 if (serverName && serverNameLength) 554 { 555 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServerItemAttr), 556 CssmData(const_cast<char *>(serverName), serverNameLength)); 557 } 558 559 if (securityDomain && securityDomainLength) 560 { 561 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecSecurityDomainItemAttr), 562 CssmData (const_cast<char*>(securityDomain), securityDomainLength)); 563 } 564 565 if (accountName && accountNameLength) 566 { 567 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr), 568 CssmData (const_cast<char*>(accountName), accountNameLength)); 569 } 570 571 if (port) 572 { 573 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPortItemAttr), 574 UInt32(port)); 575 } 576 577 if (protocol) 578 { 579 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecProtocolItemAttr), 580 protocol); 581 } 582 583 if (authenticationType) 584 { 585 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAuthenticationTypeItemAttr), 586 authenticationType); 587 } 588 589 if (path && pathLength) 590 { 591 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPathItemAttr), path); 592 } 593 594 Item item; 595 if (!cursor->next(item)) 596 return errSecItemNotFound; 597 598 // Get its data (only if necessary) 599 if (passwordData || passwordLength) 600 { 601 CssmDataContainer outData; 602 item->getData(outData); 603 *passwordLength=(UInt32)outData.length(); 604 outData.Length=0; 605 *passwordData=outData.data(); 606 outData.Data=NULL; 607 } 608 609 if (itemRef) 610 *itemRef=item->handle(); 611 612 END_SECAPI 613} 614 615 616OSStatus 617SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) 618{ 619 BEGIN_SECAPI 620 621 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL); 622 // @@@ Get real itemClass 623 624 Item item(kSecGenericPasswordItemClass, 'aapl', passwordLength, passwordData, false); 625 626 if (serviceName && serviceNameLength) 627 { 628 CssmData service(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength); 629 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); 630 // use service name as default label (UNLESS the service is iTools and we have an account name [3787371]) 631 const char *iTools = "iTools"; 632 if (accountNameLength && serviceNameLength==strlen(iTools) && !memcmp(serviceName, iTools, serviceNameLength)) 633 { 634 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength); 635 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account); 636 } 637 else 638 { 639 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); 640 } 641 } 642 643 if (accountName && accountNameLength) 644 { 645 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength); 646 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); 647 } 648 649 Keychain keychain = nil; 650 try 651 { 652 keychain = Keychain::optional(keychainRef); 653 if ( !keychain->exists() ) 654 { 655 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. 656 } 657 } 658 catch(...) 659 { 660 keychain = globals().storageManager.defaultKeychainUI(item); 661 } 662 663 keychain->add(item); 664 if (itemRef) 665 *itemRef = item->handle(); 666 667 END_SECAPI 668} 669 670 671OSStatus 672SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef) 673 674{ 675 BEGIN_SECAPI 676 677 StorageManager::KeychainList keychains; 678 globals().storageManager.optionalSearchList(keychainOrArray, keychains); 679 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); 680 681 if (serviceName && serviceNameLength) 682 { 683 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), 684 CssmData(const_cast<char *>(serviceName), serviceNameLength)); 685 } 686 687 if (accountName && accountNameLength) 688 { 689 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr), 690 CssmData(const_cast<char *>(accountName), accountNameLength)); 691 } 692 693 Item item; 694 if (!cursor->next(item)) 695 return errSecItemNotFound; 696 697 // Get its data (only if necessary) 698 if (passwordData || passwordLength) 699 { 700 CssmDataContainer outData; 701 item->getData(outData); 702 *passwordLength=(UInt32)outData.length(); 703 outData.Length=0; 704 *passwordData=outData.data(); 705 outData.Data=NULL; 706 } 707 708 if (itemRef) 709 *itemRef=item->handle(); 710 711 END_SECAPI 712} 713 714 715OSStatus 716SecKeychainSetUserInteractionAllowed(Boolean state) 717{ 718 BEGIN_SECAPI 719 720 globals().setUserInteractionAllowed(state); 721 722 END_SECAPI 723} 724 725 726OSStatus 727SecKeychainGetUserInteractionAllowed(Boolean *state) 728{ 729 BEGIN_SECAPI 730 731 Required(state)=globals().getUserInteractionAllowed(); 732 733 END_SECAPI 734} 735 736 737OSStatus 738SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle) 739{ 740 BEGIN_SECAPI 741 742 RequiredParam(dldbHandle); 743 744 Keychain keychain = Keychain::optional(keychainRef); 745 *dldbHandle = keychain->database()->handle(); 746 747 END_SECAPI 748} 749 750 751OSStatus 752SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle) 753{ 754 BEGIN_SECAPI 755 756 RequiredParam(cspHandle); 757 758 Keychain keychain = Keychain::optional(keychainRef); 759 *cspHandle = keychain->csp()->handle(); 760 761 END_SECAPI 762} 763 764 765OSStatus 766SecKeychainCopyAccess(SecKeychainRef keychainRef, SecAccessRef *accessRef) 767{ 768 BEGIN_SECAPI 769 770 MacOSError::throwMe(errSecUnimplemented);//%%%for now 771 772 END_SECAPI 773} 774 775 776OSStatus 777SecKeychainSetAccess(SecKeychainRef keychainRef, SecAccessRef accessRef) 778{ 779 BEGIN_SECAPI 780 781 MacOSError::throwMe(errSecUnimplemented);//%%%for now 782 783 END_SECAPI 784} 785 786 787#pragma mark ---- Private API ---- 788 789 790OSStatus 791SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) 792{ 793 BEGIN_SECAPI 794 795 Keychain keychain = Keychain::optional(keychainRef); 796 keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword); 797 798 END_SECAPI 799} 800 801 802OSStatus 803SecKeychainCopyLogin(SecKeychainRef *keychainRef) 804{ 805 BEGIN_SECAPI 806 807 RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle(); 808 809 END_SECAPI 810} 811 812 813OSStatus 814SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password) 815{ 816 BEGIN_SECAPI 817 818 try 819 { 820 if (password) { 821 globals().storageManager.login(nameLength, name, passwordLength, password); 822 } else { 823 globals().storageManager.stashLogin(); 824 } 825 } 826 catch (CommonError &e) 827 { 828 if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED) 829 { 830 return errSecAuthFailed; 831 } 832 else 833 { 834 return e.osStatus(); 835 } 836 } 837 838 END_SECAPI 839} 840 841OSStatus SecKeychainStash() 842{ 843 BEGIN_SECAPI 844 845 try 846 { 847 globals().storageManager.stashKeychain(); 848 } 849 catch (CommonError &e) 850 { 851 if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED) 852 { 853 return errSecAuthFailed; 854 } 855 else 856 { 857 return e.osStatus(); 858 } 859 } 860 861 END_SECAPI 862} 863 864OSStatus 865SecKeychainLogout() 866{ 867 BEGIN_SECAPI 868 869 globals().storageManager.logout(); 870 871 END_SECAPI 872} 873 874/* (non-exported C utility routine) 'Makes' a keychain based on a full path 875*/ 876static Keychain make(const char *name) 877{ 878 return globals().storageManager.make(name); 879} 880 881/* 'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs. 882 Note this version doesn't take an accessRef or password. 883 The "KC" create API takes a keychainRef... 884*/ 885OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef) 886{ 887 BEGIN_SECAPI 888 RequiredParam(fullPathName); 889 RequiredParam(keychainRef)=make(fullPathName)->handle(); 890 END_SECAPI 891} 892 893 894/* Determines if the keychainRef is a valid keychain. 895*/ 896OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) 897{ 898 BEGIN_SECAPI 899 *isValid = false; 900 if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL) 901 *isValid = true; 902 END_SECAPI 903} 904 905/* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs. 906*/ 907OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) 908{ 909 BEGIN_SECAPI 910 StorageManager::KeychainList singleton; 911 singleton.push_back(KeychainImpl::required(keychainRef)); 912 globals().storageManager.remove(singleton); 913 END_SECAPI 914} 915 916/* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs. 917*/ 918OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword) 919{ 920 BEGIN_SECAPI 921 RequiredParam(inPassword); 922 KeychainImpl::required(keychainRef)->create(passwordLength, inPassword); 923 END_SECAPI 924} 925 926/* Modify a keychain so that it can be synchronized. 927*/ 928OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData) 929{ 930 BEGIN_SECAPI 931 932 // do error checking for required parameters 933 RequiredParam(dbBlobArray); 934 RequiredParam(extraData); 935 936 const CssmData extraCssmData(const_cast<UInt8 *>(CFDataGetBytePtr(extraData)), 937 CFDataGetLength(extraData)); 938 939 CFIndex dbBlobArrayCount = CFArrayGetCount(dbBlobArray); 940 size_t space = sizeof(uint8) + (dbBlobArrayCount * sizeof(SecurityServer::DbHandle)); 941 void *dataPtr = (void*)malloc(space); 942 if ( !dataPtr ) 943 return errSecAllocate; 944 // 945 // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with. 946 // 947 uint8* sizePtr = (uint8*)dataPtr; 948 *sizePtr = dbBlobArrayCount; 949 SecurityServer::DbHandle *currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1); 950 CFIndex index; 951 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard()); 952 for (index=0; index < dbBlobArrayCount; index++) 953 { 954 CFDataRef cfBlobData = (CFDataRef)CFArrayGetValueAtIndex(dbBlobArray, index); 955 const CssmData thisKCData(const_cast<UInt8 *>(CFDataGetBytePtr(cfBlobData)), CFDataGetLength(cfBlobData)); 956 // 957 // Since it's to a DbHandle that's not on our disk (it came from user's iDisk), 958 // it's OK to use the mIdentifier and access credentials of the keychain we're recoding. 959 // 960 Keychain kc = KeychainImpl::required(keychainRef); 961 *currDbHandle = ss.decodeDb(kc->dlDbIdentifier(), kc->defaultCredentials(), thisKCData); /* returns a DbHandle (IPCDbHandle) */ 962 963 currDbHandle++; 964 } 965 // do the work 966 Keychain keychain = Keychain::optional(keychainRef); 967 const CssmData data(const_cast<UInt8 *>((uint8*)dataPtr), space); 968 Boolean recodeFailed = false; 969 970 int errCode=errSecSuccess; 971 972 try 973 { 974 keychain->recode(data, extraCssmData); 975 } 976 catch (MacOSError e) 977 { 978 errCode = e.osStatus(); 979 recodeFailed = true; 980 } 981 catch (UnixError ue) 982 { 983 errCode = ue.unixError(); 984 } 985 986 currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1); 987 for (index=0; index < dbBlobArrayCount; index++) 988 { 989 ss.releaseDb(*currDbHandle); 990 currDbHandle++; 991 } 992 if ( dataPtr ) 993 free(dataPtr); 994 995 if ( recodeFailed ) 996 { 997 return errCode; 998 } 999 1000 END_SECAPI 1001} 1002 1003OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature) 1004{ 1005 BEGIN_SECAPI 1006 1007 // do error checking for required parameters 1008 RequiredParam(keychainSignature); 1009 1010 // make a keychain object "wrapper" for this keychain ref 1011 Keychain keychain = Keychain::optional(keychainRef); 1012 CssmAutoData data(keychain->database()->allocator()); 1013 keychain->copyBlob(data.get()); 1014 1015 // get the cssmDBBlob 1016 const SecurityServer::DbBlob *cssmDBBlob = 1017 data.get().interpretedAs<const SecurityServer::DbBlob>(); 1018 1019 // convert from CDSA standards to CF standards 1020 *keychainSignature = CFDataCreate(kCFAllocatorDefault, 1021 cssmDBBlob->randomSignature.bytes, 1022 sizeof(SecurityServer::DbBlob::Signature)); 1023 1024 END_SECAPI 1025} 1026 1027OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) 1028{ 1029 BEGIN_SECAPI 1030 1031 // do error checking for required parameters 1032 RequiredParam(dbBlob); 1033 1034 // make a keychain object "wrapper" for this keychain ref 1035 Keychain keychain = Keychain::optional(keychainRef); 1036 CssmAutoData data(keychain->database()->allocator()); 1037 keychain->copyBlob(data.get()); 1038 1039 // convert from CDSA standards to CF standards 1040 *dbBlob = CFDataCreate(kCFAllocatorDefault, data, data.length()); 1041 1042 END_SECAPI 1043} 1044 1045// make a new keychain with pre-existing secrets 1046OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef) 1047{ 1048 BEGIN_SECAPI 1049 1050 KCThrowParamErrIf_(!fullPathName); 1051 KCThrowParamErrIf_(!dbBlob); 1052 1053 Keychain keychain = globals().storageManager.make(fullPathName); 1054 1055 CssmData blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob)), CFDataGetLength(dbBlob)); 1056 1057 // @@@ the call to StorageManager::make above leaves keychain the the cache. 1058 // If the create below fails we should probably remove it. 1059 keychain->createWithBlob(blob); 1060 1061 RequiredParam(kcRef)=keychain->handle(); 1062 1063 // 1064 1065 END_SECAPI 1066} 1067 1068// add a non-file based DB to the keychain list 1069OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, 1070 const CSSM_GUID *guid, uint32 subServiceType) 1071{ 1072 BEGIN_SECAPI 1073 1074 RequiredParam(dbName); 1075 StorageManager &smr = globals().storageManager; 1076 smr.addToDomainList(domain, dbName, *guid, subServiceType); 1077 1078 END_SECAPI 1079} 1080 1081// determine if a non-file based DB is in the keychain list 1082OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, 1083 const CSSM_GUID *guid, uint32 subServiceType) 1084{ 1085 BEGIN_SECAPI 1086 RequiredParam(dbName); 1087 StorageManager &smr = globals().storageManager; 1088 smr.isInDomainList(domain, dbName, *guid, subServiceType); 1089 END_SECAPI 1090} 1091 1092// remove a non-file based DB from the keychain list 1093OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, 1094 const CSSM_GUID *guid, uint32 subServiceType) 1095{ 1096 BEGIN_SECAPI 1097 RequiredParam(dbName); 1098 StorageManager &smr = globals().storageManager; 1099 smr.removeFromDomainList(domain, dbName, *guid, subServiceType); 1100 END_SECAPI 1101} 1102 1103 1104// set server mode -- must be called before any other Sec* etc. call 1105void SecKeychainSetServerMode() 1106{ 1107 gServerMode = true; 1108} 1109 1110 1111 1112OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) 1113{ 1114 BEGIN_SECAPI 1115 RequiredParam(kcRef); 1116 Keychain keychain = Keychain::optional(kcRef); 1117 keychain->setBatchMode(mode, rollback); 1118 END_SECAPI 1119} 1120 1121 1122 1123OSStatus SecKeychainCleanupHandles() 1124{ 1125 BEGIN_SECAPI 1126 END_SECAPI // which causes the handle cache cleanup routine to run 1127} 1128 1129OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) 1130{ 1131 BEGIN_SECAPI 1132 SecurityServer::ClientSession().verifyKeyStorePassphrase(retries); 1133 END_SECAPI 1134} 1135 1136OSStatus SecKeychainChangeKeyStorePassphrase() 1137{ 1138 BEGIN_SECAPI 1139 SecurityServer::ClientSession().changeKeyStorePassphrase(); 1140 END_SECAPI 1141}