-/*
- * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <Security/SecKeychain.h>
-#include <Security/SecKeychainPriv.h>
-#include <security_keychain/KCCursor.h>
-#include <security_cdsa_utilities/cssmdata.h>
-#include <security_cdsa_client/wrapkey.h>
-#include <security_keychain/KCExceptions.h>
-#include <securityd_client/ssblob.h>
-#include <Security/SecAccess.h>
-#include <Security/SecTrustedApplicationPriv.h>
-#include "SecBridge.h"
-#include "CCallbackMgr.h"
-#include <security_cdsa_utilities/Schema.h>
-#include <security_cdsa_client/mdsclient.h>
-#include <pwd.h>
-
-OSStatus
-SecKeychainMDSInstall()
-{
- BEGIN_SECAPI
-
- Security::MDSClient::Directory d;
- d.install();
-
- END_SECAPI
-}
-
-CFTypeID
-SecKeychainGetTypeID(void)
-{
- BEGIN_SECAPI
-
- return gTypes().KeychainImpl.typeID;
-
- END_SECAPI1(_kCFRuntimeNotATypeID)
-}
-
-
-OSStatus
-SecKeychainGetVersion(UInt32 *returnVers)
-{
- if (!returnVers)
- return errSecSuccess;
-
- *returnVers = 0x02028000;
- return errSecSuccess;
-}
-
-
-OSStatus
-SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName,
- const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain)
-{
- BEGIN_SECAPI
-
- // range check parameters
- RequiredParam (guid);
- RequiredParam (dbName);
-
- // create a DLDbIdentifier that describes what should be opened
- const CSSM_VERSION *version = NULL;
- const CssmSubserviceUid ssuid(*guid, version, subserviceId, subserviceType);
- DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation);
-
- // make a keychain from the supplied info
- RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false)->handle ();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password,
- Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- KCThrowParamErrIf_(!pathName);
- Keychain keychain = globals().storageManager.make(pathName);
-
- // @@@ the call to StorageManager::make above leaves keychain the the cache.
- // If the create below fails we should probably remove it.
- if(promptUser)
- keychain->create();
- else
- {
- KCThrowParamErrIf_(!password);
- keychain->create(passwordLength, password);
- }
-
- RequiredParam(keychainRef)=keychain->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainDelete(SecKeychainRef keychainOrArray)
-{
- BEGIN_SECAPI
-
- KCThrowIf_(!keychainOrArray, errSecInvalidKeychain);
- StorageManager::KeychainList keychains;
- globals().storageManager.optionalSearchList(keychainOrArray, keychains);
-
- globals().storageManager.remove(keychains, true);
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
- if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
- {
- UInt32 lockInterval=newSettings->lockInterval;
- bool lockOnSleep=newSettings->lockOnSleep;
- keychain->setSettings(lockInterval, lockOnSleep);
- }
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
- if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
- {
- uint32 lockInterval;
- bool lockOnSleep;
-
- keychain->getSettings(lockInterval, lockOnSleep);
- outSettings->lockInterval=lockInterval;
- outSettings->lockOnSleep=lockOnSleep;
- }
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void *password, Boolean usePassword)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
-
- if (usePassword)
- keychain->unlock(CssmData(const_cast<void *>(password), passwordLength));
- else
- keychain->unlock();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainLock(SecKeychainRef keychainRef)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
- keychain->lock();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainLockAll(void)
-{
- BEGIN_SECAPI
-
- globals().storageManager.lockAll();
-
- END_SECAPI
-}
-
-
-OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList)
-{
- BEGIN_SECAPI
- //
- // Get the current user (using fallback method if necessary)
- //
- char* uName = getenv("USER");
- string userName = uName ? uName : "";
- if ( userName.length() == 0 )
- {
- uid_t uid = geteuid();
- if (!uid) uid = getuid();
- struct passwd *pw = getpwuid(uid); // fallback case...
- if (pw)
- userName = pw->pw_name;
- endpwent();
- }
- if ( userName.length() == 0 ) // did we ultimately get one?
- MacOSError::throwMe(errAuthorizationInternal);
-
- SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData());
-
- if (password)
- {
- // Clear the plist and move aside (rename) the existing login.keychain
- globals().storageManager.resetKeychain(resetSearchList);
-
- // Create the login keychain without UI
- globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password);
-
- // Set it as the default
- Keychain keychain = globals().storageManager.loginKeychain();
- globals().storageManager.defaultKeychain(keychain);
- }
- else
- {
- // Create the login keychain, prompting for password
- // (implicitly calls resetKeychain, login, and defaultKeychain)
- globals().storageManager.makeLoginAuthUI(NULL);
- }
-
- // Post a "list changed" event after a reset, so apps can refresh their list.
- // Make sure we are not holding mLock when we post this event.
- KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
-
- END_SECAPI
-}
-
-OSStatus
-SecKeychainCopyDefault(SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- RequiredParam(keychainRef)=globals().storageManager.defaultKeychain()->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainSetDefault(SecKeychainRef keychainRef)
-{
- BEGIN_SECAPI
-
- globals().storageManager.defaultKeychain(Keychain::optional(keychainRef));
-
- END_SECAPI
-}
-
-OSStatus SecKeychainCopySearchList(CFArrayRef *searchList)
-{
- BEGIN_SECAPI
-
- RequiredParam(searchList);
- StorageManager &smr = globals().storageManager;
- StorageManager::KeychainList keychainList;
- smr.getSearchList(keychainList);
- *searchList = smr.convertFromKeychainList(keychainList);
-
- END_SECAPI
-}
-
-OSStatus SecKeychainSetSearchList(CFArrayRef searchList)
-{
- BEGIN_SECAPI
-
- RequiredParam(searchList);
- StorageManager &smr = globals().storageManager;
- StorageManager::KeychainList keychainList;
- smr.convertToKeychainList(searchList, keychainList);
- smr.setSearchList(keychainList);
-
- END_SECAPI
-}
-
-OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle();
-
- END_SECAPI
-}
-
-OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef)
-{
- BEGIN_SECAPI
-
- globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef));
-
- END_SECAPI
-}
-
-OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef *searchList)
-{
- BEGIN_SECAPI
-
- RequiredParam(searchList);
- StorageManager &smr = globals().storageManager;
- StorageManager::KeychainList keychainList;
- smr.getSearchList(domain, keychainList);
- *searchList = smr.convertFromKeychainList(keychainList);
-
- END_SECAPI
-}
-
-OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList)
-{
- BEGIN_SECAPI
-
- RequiredParam(searchList);
- StorageManager &smr = globals().storageManager;
- StorageManager::KeychainList keychainList;
- smr.convertToKeychainList(searchList, keychainList);
- smr.setSearchList(domain, keychainList);
-
- END_SECAPI
-}
-
-OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain)
-{
- BEGIN_SECAPI
-
- globals().storageManager.domain(domain);
-
- END_SECAPI
-}
-
-OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain)
-{
- BEGIN_SECAPI
-
- *domain = globals().storageManager.domain();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainGetStatus(SecKeychainRef keychainRef, SecKeychainStatus *keychainStatus)
-{
- BEGIN_SECAPI
-
- RequiredParam(keychainStatus) = (SecKeychainStatus)Keychain::optional(keychainRef)->status();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathName)
-{
- BEGIN_SECAPI
-
- RequiredParam(pathName);
- RequiredParam(ioPathLength);
-
- const char *name = Keychain::optional(keychainRef)->name();
- UInt32 nameLen = (UInt32)strlen(name);
- UInt32 callersLen = *ioPathLength;
- *ioPathLength = nameLen;
- if (nameLen+1 > callersLen) // if the client's buffer is too small (including null-termination), throw
- return errSecBufferTooSmall;
- strncpy(pathName, name, nameLen);
- pathName[nameLen] = 0;
- *ioPathLength = nameLen; // set the length.
-
- END_SECAPI
-}
-
-
-// @@@ Deprecated
-UInt16
-SecKeychainListGetCount(void)
-{
- BEGIN_SECAPI
-
- return globals().storageManager.size();
-
- END_SECAPI1(0)
-}
-
-
-// @@@ Deprecated
-OSStatus
-SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- KeychainCore::StorageManager &smgr=KeychainCore::globals().storageManager;
- RequiredParam(keychainRef)=smgr[index]->handle();
-
- END_SECAPI
-}
-
-
-// @@@ Deprecated
-OSStatus
-SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- Required(keychainRef);
- Keychain keychain = Keychain::optional(*keychainRef);
- StorageManager::KeychainList keychainList;
- keychainList.push_back(keychain);
- globals().storageManager.remove(keychainList);
- *keychainRef = NULL;
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef, UInt32 itemID, SecKeychainAttributeInfo **info)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
- keychain->getAttributeInfoForItemID(itemID, info);
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info)
-{
- BEGIN_SECAPI
-
- KeychainImpl::freeAttributeInfo(info);
-
- END_SECAPI
-}
-
-
-pascal OSStatus
-SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext)
-{
- BEGIN_SECAPI
-
- RequiredParam(callbackFunction);
- CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext);
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainRemoveCallback(SecKeychainCallback callbackFunction)
-{
- BEGIN_SECAPI
-
- RequiredParam(callbackFunction);
- CCallbackMgr::RemoveCallback(callbackFunction);
-
- END_SECAPI
-}
-
-OSStatus
-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)
-{
- BEGIN_SECAPI
-
- KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
- // @@@ Get real itemClass
- Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false);
-
- if (serverName && serverNameLength)
- {
- CssmData server(const_cast<void *>(reinterpret_cast<const void *>(serverName)), serverNameLength);
- item->setAttribute(Schema::attributeInfo(kSecServerItemAttr), server);
- // use server name as default label
- item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), server);
- }
-
- if (accountName && accountNameLength)
- {
- CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
- item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
- }
-
- if (securityDomain && securityDomainLength)
- item->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr),
- CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain)), securityDomainLength));
-
- item->setAttribute(Schema::attributeInfo(kSecPortItemAttr), UInt32(port));
- item->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr), protocol);
- item->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr), authenticationType);
-
- if (path && pathLength)
- item->setAttribute(Schema::attributeInfo(kSecPathItemAttr),
- CssmData(const_cast<void *>(reinterpret_cast<const void *>(path)), pathLength));
-
- Keychain keychain = nil;
- try
- {
- keychain = Keychain::optional(keychainRef);
- if ( !keychain->exists() )
- {
- MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
- }
- }
- catch(...)
- {
- keychain = globals().storageManager.defaultKeychainUI(item);
- }
-
- keychain->add(item);
-
- if (itemRef)
- *itemRef = item->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-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)
-
-{
- BEGIN_SECAPI
-
- StorageManager::KeychainList keychains;
- globals().storageManager.optionalSearchList(keychainOrArray, keychains);
- KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL);
-
- if (serverName && serverNameLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServerItemAttr),
- CssmData(const_cast<char *>(serverName), serverNameLength));
- }
-
- if (securityDomain && securityDomainLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecSecurityDomainItemAttr),
- CssmData (const_cast<char*>(securityDomain), securityDomainLength));
- }
-
- if (accountName && accountNameLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
- CssmData (const_cast<char*>(accountName), accountNameLength));
- }
-
- if (port)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPortItemAttr),
- UInt32(port));
- }
-
- if (protocol)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecProtocolItemAttr),
- protocol);
- }
-
- if (authenticationType)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAuthenticationTypeItemAttr),
- authenticationType);
- }
-
- if (path && pathLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPathItemAttr), path);
- }
-
- Item item;
- if (!cursor->next(item))
- return errSecItemNotFound;
-
- // Get its data (only if necessary)
- if (passwordData || passwordLength)
- {
- CssmDataContainer outData;
- item->getData(outData);
- *passwordLength=(UInt32)outData.length();
- outData.Length=0;
- *passwordData=outData.data();
- outData.Data=NULL;
- }
-
- if (itemRef)
- *itemRef=item->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef)
-{
- BEGIN_SECAPI
-
- KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
- // @@@ Get real itemClass
-
- Item item(kSecGenericPasswordItemClass, 'aapl', passwordLength, passwordData, false);
-
- if (serviceName && serviceNameLength)
- {
- CssmData service(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength);
- item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
- // use service name as default label (UNLESS the service is iTools and we have an account name [3787371])
- const char *iTools = "iTools";
- if (accountNameLength && serviceNameLength==strlen(iTools) && !memcmp(serviceName, iTools, serviceNameLength))
- {
- CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
- item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account);
- }
- else
- {
- item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
- }
- }
-
- if (accountName && accountNameLength)
- {
- CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
- item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
- }
-
- Keychain keychain = nil;
- try
- {
- keychain = Keychain::optional(keychainRef);
- if ( !keychain->exists() )
- {
- MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
- }
- }
- catch(...)
- {
- keychain = globals().storageManager.defaultKeychainUI(item);
- }
-
- keychain->add(item);
- if (itemRef)
- *itemRef = item->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef)
-
-{
- BEGIN_SECAPI
-
- StorageManager::KeychainList keychains;
- globals().storageManager.optionalSearchList(keychainOrArray, keychains);
- KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
-
- if (serviceName && serviceNameLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr),
- CssmData(const_cast<char *>(serviceName), serviceNameLength));
- }
-
- if (accountName && accountNameLength)
- {
- cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
- CssmData(const_cast<char *>(accountName), accountNameLength));
- }
-
- Item item;
- if (!cursor->next(item))
- return errSecItemNotFound;
-
- // Get its data (only if necessary)
- if (passwordData || passwordLength)
- {
- CssmDataContainer outData;
- item->getData(outData);
- *passwordLength=(UInt32)outData.length();
- outData.Length=0;
- *passwordData=outData.data();
- outData.Data=NULL;
- }
-
- if (itemRef)
- *itemRef=item->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainSetUserInteractionAllowed(Boolean state)
-{
- BEGIN_SECAPI
-
- globals().setUserInteractionAllowed(state);
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainGetUserInteractionAllowed(Boolean *state)
-{
- BEGIN_SECAPI
-
- Required(state)=globals().getUserInteractionAllowed();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle)
-{
- BEGIN_SECAPI
-
- RequiredParam(dldbHandle);
-
- Keychain keychain = Keychain::optional(keychainRef);
- *dldbHandle = keychain->database()->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
-{
- BEGIN_SECAPI
-
- RequiredParam(cspHandle);
-
- Keychain keychain = Keychain::optional(keychainRef);
- *cspHandle = keychain->csp()->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainCopyAccess(SecKeychainRef keychainRef, SecAccessRef *accessRef)
-{
- BEGIN_SECAPI
-
- MacOSError::throwMe(errSecUnimplemented);//%%%for now
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainSetAccess(SecKeychainRef keychainRef, SecAccessRef accessRef)
-{
- BEGIN_SECAPI
-
- MacOSError::throwMe(errSecUnimplemented);//%%%for now
-
- END_SECAPI
-}
-
-
-#pragma mark ---- Private API ----
-
-
-OSStatus
-SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword)
-{
- BEGIN_SECAPI
-
- Keychain keychain = Keychain::optional(keychainRef);
- keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword);
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainCopyLogin(SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
-
- RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle();
-
- END_SECAPI
-}
-
-
-OSStatus
-SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password)
-{
- BEGIN_SECAPI
-
- try
- {
- if (password) {
- globals().storageManager.login(nameLength, name, passwordLength, password);
- } else {
- globals().storageManager.stashLogin();
- }
- }
- catch (CommonError &e)
- {
- if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED)
- {
- return errSecAuthFailed;
- }
- else
- {
- return e.osStatus();
- }
- }
-
- END_SECAPI
-}
-
-OSStatus SecKeychainStash()
-{
- BEGIN_SECAPI
-
- try
- {
- globals().storageManager.stashKeychain();
- }
- catch (CommonError &e)
- {
- if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED)
- {
- return errSecAuthFailed;
- }
- else
- {
- return e.osStatus();
- }
- }
-
- END_SECAPI
-}
-
-OSStatus
-SecKeychainLogout()
-{
- BEGIN_SECAPI
-
- globals().storageManager.logout();
-
- END_SECAPI
-}
-
-/* (non-exported C utility routine) 'Makes' a keychain based on a full path
-*/
-static Keychain make(const char *name)
-{
- return globals().storageManager.make(name);
-}
-
-/* 'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs.
- Note this version doesn't take an accessRef or password.
- The "KC" create API takes a keychainRef...
-*/
-OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef)
-{
- BEGIN_SECAPI
- RequiredParam(fullPathName);
- RequiredParam(keychainRef)=make(fullPathName)->handle();
- END_SECAPI
-}
-
-
-/* Determines if the keychainRef is a valid keychain.
-*/
-OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
-{
- BEGIN_SECAPI
- *isValid = false;
- if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL)
- *isValid = true;
- END_SECAPI
-}
-
-/* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs.
-*/
-OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef)
-{
- BEGIN_SECAPI
- StorageManager::KeychainList singleton;
- singleton.push_back(KeychainImpl::required(keychainRef));
- globals().storageManager.remove(singleton);
- END_SECAPI
-}
-
-/* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs.
-*/
-OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword)
-{
- BEGIN_SECAPI
- RequiredParam(inPassword);
- KeychainImpl::required(keychainRef)->create(passwordLength, inPassword);
- END_SECAPI
-}
-
-/* Modify a keychain so that it can be synchronized.
-*/
-OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData)
-{
- BEGIN_SECAPI
-
- // do error checking for required parameters
- RequiredParam(dbBlobArray);
- RequiredParam(extraData);
-
- const CssmData extraCssmData(const_cast<UInt8 *>(CFDataGetBytePtr(extraData)),
- CFDataGetLength(extraData));
-
- CFIndex dbBlobArrayCount = CFArrayGetCount(dbBlobArray);
- size_t space = sizeof(uint8) + (dbBlobArrayCount * sizeof(SecurityServer::DbHandle));
- void *dataPtr = (void*)malloc(space);
- if ( !dataPtr )
- return errSecAllocate;
- //
- // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with.
- //
- uint8* sizePtr = (uint8*)dataPtr;
- *sizePtr = dbBlobArrayCount;
- SecurityServer::DbHandle *currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1);
- CFIndex index;
- SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard());
- for (index=0; index < dbBlobArrayCount; index++)
- {
- CFDataRef cfBlobData = (CFDataRef)CFArrayGetValueAtIndex(dbBlobArray, index);
- const CssmData thisKCData(const_cast<UInt8 *>(CFDataGetBytePtr(cfBlobData)), CFDataGetLength(cfBlobData));
- //
- // Since it's to a DbHandle that's not on our disk (it came from user's iDisk),
- // it's OK to use the mIdentifier and access credentials of the keychain we're recoding.
- //
- Keychain kc = KeychainImpl::required(keychainRef);
- *currDbHandle = ss.decodeDb(kc->dlDbIdentifier(), kc->defaultCredentials(), thisKCData); /* returns a DbHandle (IPCDbHandle) */
-
- currDbHandle++;
- }
- // do the work
- Keychain keychain = Keychain::optional(keychainRef);
- const CssmData data(const_cast<UInt8 *>((uint8*)dataPtr), space);
- Boolean recodeFailed = false;
-
- int errCode=errSecSuccess;
-
- try
- {
- keychain->recode(data, extraCssmData);
- }
- catch (MacOSError e)
- {
- errCode = e.osStatus();
- recodeFailed = true;
- }
- catch (UnixError ue)
- {
- errCode = ue.unixError();
- }
-
- currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1);
- for (index=0; index < dbBlobArrayCount; index++)
- {
- ss.releaseDb(*currDbHandle);
- currDbHandle++;
- }
- if ( dataPtr )
- free(dataPtr);
-
- if ( recodeFailed )
- {
- return errCode;
- }
-
- END_SECAPI
-}
-
-OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature)
-{
- BEGIN_SECAPI
-
- // do error checking for required parameters
- RequiredParam(keychainSignature);
-
- // make a keychain object "wrapper" for this keychain ref
- Keychain keychain = Keychain::optional(keychainRef);
- CssmAutoData data(keychain->database()->allocator());
- keychain->copyBlob(data.get());
-
- // get the cssmDBBlob
- const SecurityServer::DbBlob *cssmDBBlob =
- data.get().interpretedAs<const SecurityServer::DbBlob>();
-
- // convert from CDSA standards to CF standards
- *keychainSignature = CFDataCreate(kCFAllocatorDefault,
- cssmDBBlob->randomSignature.bytes,
- sizeof(SecurityServer::DbBlob::Signature));
-
- END_SECAPI
-}
-
-OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob)
-{
- BEGIN_SECAPI
-
- // do error checking for required parameters
- RequiredParam(dbBlob);
-
- // make a keychain object "wrapper" for this keychain ref
- Keychain keychain = Keychain::optional(keychainRef);
- CssmAutoData data(keychain->database()->allocator());
- keychain->copyBlob(data.get());
-
- // convert from CDSA standards to CF standards
- *dbBlob = CFDataCreate(kCFAllocatorDefault, data, data.length());
-
- END_SECAPI
-}
-
-// make a new keychain with pre-existing secrets
-OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef)
-{
- BEGIN_SECAPI
-
- KCThrowParamErrIf_(!fullPathName);
- KCThrowParamErrIf_(!dbBlob);
-
- Keychain keychain = globals().storageManager.make(fullPathName);
-
- CssmData blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob)), CFDataGetLength(dbBlob));
-
- // @@@ the call to StorageManager::make above leaves keychain the the cache.
- // If the create below fails we should probably remove it.
- keychain->createWithBlob(blob);
-
- RequiredParam(kcRef)=keychain->handle();
-
- //
-
- END_SECAPI
-}
-
-// add a non-file based DB to the keychain list
-OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName,
- const CSSM_GUID *guid, uint32 subServiceType)
-{
- BEGIN_SECAPI
-
- RequiredParam(dbName);
- StorageManager &smr = globals().storageManager;
- smr.addToDomainList(domain, dbName, *guid, subServiceType);
-
- END_SECAPI
-}
-
-// determine if a non-file based DB is in the keychain list
-OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName,
- const CSSM_GUID *guid, uint32 subServiceType)
-{
- BEGIN_SECAPI
- RequiredParam(dbName);
- StorageManager &smr = globals().storageManager;
- smr.isInDomainList(domain, dbName, *guid, subServiceType);
- END_SECAPI
-}
-
-// remove a non-file based DB from the keychain list
-OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName,
- const CSSM_GUID *guid, uint32 subServiceType)
-{
- BEGIN_SECAPI
- RequiredParam(dbName);
- StorageManager &smr = globals().storageManager;
- smr.removeFromDomainList(domain, dbName, *guid, subServiceType);
- END_SECAPI
-}
-
-
-// set server mode -- must be called before any other Sec* etc. call
-void SecKeychainSetServerMode()
-{
- gServerMode = true;
-}
-
-
-
-OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback)
-{
- BEGIN_SECAPI
- RequiredParam(kcRef);
- Keychain keychain = Keychain::optional(kcRef);
- keychain->setBatchMode(mode, rollback);
- END_SECAPI
-}
-
-
-
-OSStatus SecKeychainCleanupHandles()
-{
- BEGIN_SECAPI
- END_SECAPI // which causes the handle cache cleanup routine to run
-}
-
-OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries)
-{
- BEGIN_SECAPI
- SecurityServer::ClientSession().verifyKeyStorePassphrase(retries);
- END_SECAPI
-}
-
-OSStatus SecKeychainChangeKeyStorePassphrase()
-{
- BEGIN_SECAPI
- SecurityServer::ClientSession().changeKeyStorePassphrase();
- END_SECAPI
-}
-
-static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRef *masterKey, CFStringRef password)
-{
- BEGIN_SECAPI
-
- // make a keychain object "wrapper" for this keychain ref
- Keychain keychain = Keychain::optional(userKeychainRef);
-
- CssmClient::Db db = keychain->database();
-
- // create the keychain, using appropriate credentials
- Allocator &alloc = db->allocator();
- AutoCredentials cred(alloc); // will leak, but we're quitting soon :-)
-
- char passphrase[1024];
- CFStringGetCString(password, passphrase, sizeof(passphrase), kCFStringEncodingUTF8);
-
- // use this passphrase
- cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
- new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD),
- new(alloc) ListElement(StringData(passphrase)));
- db->accessCredentials(&cred);
-
- CSSM_DL_DB_HANDLE dlDb = db->handle();
- CssmData dlDbData = CssmData::wrap(dlDb);
- CssmKey refKey;
- KeySpec spec(CSSM_KEYUSE_ANY,
- CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE);
-
- DeriveKey derive(keychain->csp(), CSSM_ALGID_KEYCHAIN_KEY, CSSM_ALGID_3DES_3KEY, 3 * 64);
- derive(&dlDbData, spec, refKey);
-
- // now extract the raw keybits
- CssmKey rawKey;
- WrapKey wrap(keychain->csp(), CSSM_ALGID_NONE);
- wrap(refKey, rawKey);
-
- *masterKey = CFDataCreate(kCFAllocatorDefault, rawKey.keyData(), rawKey.length());
-
- END_SECAPI
-}
-
-
-OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) {
- SecTrustedApplicationRef itemPath;
- SecAccessRef ourAccessRef = NULL;
-
- OSStatus result = errSecParam;
-
- CFDataRef masterKey = NULL;
- result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password);
- if (errSecSuccess != result) {
- return result;
- }
-
- result = SecKeychainStash();
- if (errSecSuccess != result) {
- if (NULL != masterKey) CFRelease(masterKey);
- return result;
- }
-
- CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- if ( noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath )
- CFArrayAppendValue(trustedApplications, itemPath);
-
- if ( trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) {
- if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) {
- if (NULL == systemKeychainRef) {
- SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &systemKeychainRef);
- }
-
- const void *queryKeys[] = { kSecClass,
- kSecAttrService,
- kSecAttrAccount,
- kSecUseKeychain,
- };
- const void *queryValues[] = { kSecClassGenericPassword,
- CFSTR("com.apple.loginwindow.auto-login"),
- username,
- systemKeychainRef,
- };
-
- const void *updateKeys[] = { kSecAttrAccess,
- kSecValueData,
- };
- const void *updateValues[] = { ourAccessRef,
- masterKey,
- };
-
- CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, queryKeys, queryValues, sizeof(queryValues)/sizeof(*queryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionaryRef update = CFDictionaryCreate(kCFAllocatorDefault, updateKeys, updateValues, sizeof(updateValues)/sizeof(*updateValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
- result = SecItemUpdate(query, update);
-
- if (errSecSuccess != result) {
- const void *addKeys[] = { kSecClass,
- kSecAttrService,
- kSecAttrAccount,
- kSecUseKeychain,
- kSecAttrAccess,
- kSecValueData,
- };
- const void *addValues[] = { kSecClassGenericPassword,
- CFSTR("com.apple.loginwindow.auto-login"),
- username,
- systemKeychainRef,
- ourAccessRef,
- masterKey,
- };
-
- CFDictionaryRef add = CFDictionaryCreate(kCFAllocatorDefault, addKeys, addValues, sizeof(addValues)/sizeof(*addValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- result = SecItemAdd(add, NULL);
- if (NULL != add) CFRelease(add);
- }
-
- if (NULL != query) CFRelease(query);
- if (NULL != update) CFRelease(update);
- }
- }
-
- if (NULL != masterKey) CFRelease(masterKey);
- if (NULL != trustedApplications) CFRelease(trustedApplications);
- if (NULL != ourAccessRef) CFRelease(ourAccessRef);
- if (NULL != systemKeychainRef) CFRelease(systemKeychainRef);
-
- return result;
-}