#include <security_cdsa_utilities/Schema.h>
#include <security_cdsa_client/mdsclient.h>
#include <pwd.h>
+#include <os/activity.h>
+#include <Security/AuthorizationTagsPriv.h>
+#include <Security/Authorization.h>
+#include "TokenLogin.h"
+#include "LegacyAPICounts.h"
+
+extern "C" {
+#include "ctkloginhelper.h"
+}
OSStatus
SecKeychainMDSInstall()
{
- BEGIN_SECAPI
+ BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
Security::MDSClient::Directory d;
d.install();
OSStatus
SecKeychainGetVersion(UInt32 *returnVers)
{
+ COUNTLEGACYAPI
if (!returnVers)
return errSecSuccess;
{
BEGIN_SECAPI
- RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
-
- END_SECAPI
-}
-
+ os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
-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 ();
+ RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
END_SECAPI
}
-
OSStatus
SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password,
Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
KCThrowParamErrIf_(!pathName);
- Keychain keychain = globals().storageManager.make(pathName);
+ Keychain keychain = globals().storageManager.make(pathName, true, true);
// @@@ the call to StorageManager::make above leaves keychain the the cache.
// If the create below fails we should probably remove it.
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
KCThrowIf_(!keychainOrArray, errSecInvalidKeychain);
StorageManager::KeychainList keychains;
globals().storageManager.optionalSearchList(keychainOrArray, keychains);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
Keychain keychain = Keychain::optional(keychainRef);
if (newSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
{
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
Keychain keychain = Keychain::optional(keychainRef);
if (outSettings->version==SEC_KEYCHAIN_SETTINGS_VERS1)
{
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
Keychain keychain = Keychain::optional(keychainRef);
if (usePassword)
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
Keychain keychain = Keychain::optional(keychainRef);
keychain->lock();
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
globals().storageManager.lockAll();
END_SECAPI
OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
//
// Get the current user (using fallback method if necessary)
//
endpwent();
}
if ( userName.length() == 0 ) // did we ultimately get one?
+ {
MacOSError::throwMe(errAuthorizationInternal);
-
+ }
+
+ SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData());
+ secwarning("SecKeychainResetLogin: reset AKS passphrase");
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);
+ globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password, true);
// Set it as the default
Keychain keychain = globals().storageManager.loginKeychain();
{
// Create the login keychain, prompting for password
// (implicitly calls resetKeychain, login, and defaultKeychain)
- globals().storageManager.makeLoginAuthUI(NULL);
+ globals().storageManager.makeLoginAuthUI(NULL, true);
}
-
- SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast<void *>(password), passwordLength) : CssmData());
+ secwarning("SecKeychainResetLogin: reset osx keychain");
// 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
}
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
globals().storageManager.defaultKeychain(Keychain::optional(keychainRef));
END_SECAPI
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(searchList);
StorageManager &smr = globals().storageManager;
StorageManager::KeychainList keychainList;
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(searchList);
StorageManager &smr = globals().storageManager;
StorageManager::KeychainList keychainList;
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle();
END_SECAPI
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef));
END_SECAPI
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(searchList);
StorageManager &smr = globals().storageManager;
StorageManager::KeychainList keychainList;
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
globals().storageManager.domain(domain);
END_SECAPI
OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
*domain = globals().storageManager.domain();
END_SECAPI
}
+OSStatus
+SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version)
+{
+ BEGIN_SECAPI
+
+ RequiredParam(version);
+
+ *version = Keychain::optional(keychainRef)->database()->dbBlobVersion();
+
+ END_SECAPI
+}
+
+OSStatus
+SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename)
+{
+ BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
+ RequiredParam(masterKeyFilename);
+ Keychain kc = Keychain::optional(keychain);
+
+ SecurityServer::SystemKeychainKey keychainKey(masterKeyFilename);
+ if(keychainKey.valid()) {
+ // We've managed to read the key; now, create credentials using it
+ string path = kc->name();
+
+ CssmClient::Key keychainMasterKey(kc->csp(), keychainKey.key(), true);
+ CssmClient::AclFactory::MasterKeyUnlockCredentials creds(keychainMasterKey, Allocator::standard(Allocator::sensitive));
+
+ // Attempt the migrate, using our master key as the ACL override
+ bool result = kc->keychainMigration(path, kc->database()->dbBlobVersion(), path, version, creds.getAccessCredentials());
+ if(!result) {
+ return errSecBadReq;
+ }
+ return (kc->database()->dbBlobVersion() == version ? errSecSuccess : errSecBadReq);
+ } else {
+ return errSecBadReq;
+ }
+
+ END_SECAPI
+}
+
// @@@ Deprecated
UInt16
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(callbackFunction);
CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(callbackFunction);
CCallbackMgr::RemoveCallback(callbackFunction);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
// @@@ Get real itemClass
Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
StorageManager::KeychainList keychains;
globals().storageManager.optionalSearchList(keychainOrArray, keychains);
KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL);
{
CssmDataContainer outData;
item->getData(outData);
- *passwordLength=(UInt32)outData.length();
+ if (passwordLength) {
+ *passwordLength=(UInt32)outData.length();
+ }
outData.Length=0;
- *passwordData=outData.data();
+ if (passwordData) {
+ *passwordData=outData.data();
+ }
outData.Data=NULL;
}
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
// @@@ Get real itemClass
{
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);
- }
+ item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
}
if (accountName && accountNameLength)
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
StorageManager::KeychainList keychains;
globals().storageManager.optionalSearchList(keychainOrArray, keychains);
KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
{
CssmDataContainer outData;
item->getData(outData);
- *passwordLength=(UInt32)outData.length();
+ if (passwordLength) {
+ *passwordLength=(UInt32)outData.length();
+ }
outData.Length=0;
- *passwordData=outData.data();
+ if (passwordData) {
+ *passwordData=outData.data();
+ }
outData.Data=NULL;
}
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(dldbHandle);
Keychain keychain = Keychain::optional(keychainRef);
END_SECAPI
}
+static ModuleNexus<Mutex> gSecReturnedKeychainCSPsMutex;
+static ModuleNexus<std::set<CssmClient::CSP>> gSecReturnedKeychainCSPs;
OSStatus
SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
RequiredParam(cspHandle);
Keychain keychain = Keychain::optional(keychainRef);
- *cspHandle = keychain->csp()->handle();
+
+ // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP).
+ // Keep a global pointer to it to force the CSP to stay live forever.
+ CssmClient::CSP returnedKeychainCSP = keychain->csp();
+ {
+ StLock<Mutex> _(gSecReturnedKeychainCSPsMutex());
+ gSecReturnedKeychainCSPs().insert(returnedKeychainCSP);
+ }
+ *cspHandle = returnedKeychainCSP->handle();
END_SECAPI
}
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
Keychain keychain = Keychain::optional(keychainRef);
keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle();
END_SECAPI
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
try
{
if (password) {
- globals().storageManager.login(nameLength, name, passwordLength, password);
+ globals().storageManager.login(nameLength, name, passwordLength, password, false);
} else {
globals().storageManager.stashLogin();
}
}
catch (CommonError &e)
{
+ secnotice("KCLogin", "SecKeychainLogin failed: %d, password was%s supplied", (int)e.osStatus(), password?"":" not");
if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED)
{
return errSecAuthFailed;
return e.osStatus();
}
}
-
+
+ catch (...) {
+ __secapiresult=errSecInternalComponent;
+ }
+ secnotice("KCLogin", "SecKeychainLogin result: %d, password was%s supplied", (int)__secapiresult, password?"":" not");
+
END_SECAPI
}
OSStatus SecKeychainStash()
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
try
{
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
globals().storageManager.logout();
END_SECAPI
OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef)
{
BEGIN_SECAPI
- RequiredParam(fullPathName);
+
+ RequiredParam(fullPathName);
RequiredParam(keychainRef)=make(fullPathName)->handle();
END_SECAPI
}
OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
{
BEGIN_SECAPI
- *isValid = false;
+
+ *isValid = false;
if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL)
*isValid = true;
END_SECAPI
OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
StorageManager::KeychainList singleton;
singleton.push_back(KeychainImpl::required(keychainRef));
globals().storageManager.remove(singleton);
OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
RequiredParam(inPassword);
KeychainImpl::required(keychainRef)->create(passwordLength, inPassword);
END_SECAPI
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
// do error checking for required parameters
RequiredParam(dbBlobArray);
RequiredParam(extraData);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
// do error checking for required parameters
RequiredParam(keychainSignature);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
// do error checking for required parameters
RequiredParam(dbBlob);
OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
KCThrowParamErrIf_(!fullPathName);
KCThrowParamErrIf_(!dbBlob);
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
RequiredParam(dbName);
StorageManager &smr = globals().storageManager;
smr.addToDomainList(domain, dbName, *guid, subServiceType);
const CSSM_GUID *guid, uint32 subServiceType)
{
BEGIN_SECAPI
- RequiredParam(dbName);
+
+ RequiredParam(dbName);
StorageManager &smr = globals().storageManager;
smr.isInDomainList(domain, dbName, *guid, subServiceType);
END_SECAPI
const CSSM_GUID *guid, uint32 subServiceType)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
RequiredParam(dbName);
StorageManager &smr = globals().storageManager;
smr.removeFromDomainList(domain, dbName, *guid, subServiceType);
OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
RequiredParam(kcRef);
Keychain keychain = Keychain::optional(kcRef);
keychain->setBatchMode(mode, rollback);
OSStatus SecKeychainCleanupHandles()
{
BEGIN_SECAPI
- END_SECAPI // which causes the handle cache cleanup routine to run
+
+ END_SECAPI // which causes the handle cache cleanup routine to run
}
OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries)
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
SecurityServer::ClientSession().verifyKeyStorePassphrase(retries);
END_SECAPI
}
OSStatus SecKeychainChangeKeyStorePassphrase()
{
BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
SecurityServer::ClientSession().changeKeyStorePassphrase();
END_SECAPI
}
{
BEGIN_SECAPI
+ os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
// make a keychain object "wrapper" for this keychain ref
Keychain keychain = Keychain::optional(userKeychainRef);
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();
+ db->authenticate(CSSM_DB_ACCESS_READ, &cred);
+
+ CSSM_DL_DB_HANDLE dlDb = db->handle();
CssmData dlDbData = CssmData::wrap(dlDb);
CssmKey refKey;
KeySpec spec(CSSM_KEYUSE_ANY,
END_SECAPI
}
+static const char *kAutologinPWFilePath = "/etc/kcpassword";
+static const uint32_t kObfuscatedPasswordSizeMultiple = 12;
+static const uint32_t buffer_size = 512;
+static const uint8_t kObfuscationKey[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f};
+
+static void obfuscate(void *buffer, size_t bufferLength)
+{
+ uint8_t *pBuf = (uint8_t *) buffer;
+ const uint8_t *pKey = kObfuscationKey, *eKey = pKey + sizeof( kObfuscationKey );
+
+ while (bufferLength--) {
+ *pBuf = *pBuf ^ *pKey;
+ ++pKey;
+ ++pBuf;
+ if (pKey == eKey)
+ pKey = kObfuscationKey;
+ }
+}
+
+static bool _SASetAutologinPW(CFStringRef inAutologinPW)
+{
+ bool result = false;
+ struct stat sb;
+
+ // Delete the kcpassword file if it exists already
+ if (stat(kAutologinPWFilePath, &sb) == 0)
+ unlink( kAutologinPWFilePath );
+
+ // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off.
+ if (inAutologinPW != NULL) {
+ char buffer[buffer_size];
+ const char *pwAsUTF8String = CFStringGetCStringPtr(inAutologinPW, kCFStringEncodingUTF8);
+ if (pwAsUTF8String == NULL) {
+ if (CFStringGetCString(inAutologinPW, buffer, buffer_size, kCFStringEncodingUTF8)) pwAsUTF8String = buffer;
+ }
+
+ if (pwAsUTF8String != NULL) {
+ size_t pwLength = strlen(pwAsUTF8String) + 1;
+ size_t obfuscatedPWLength;
+ char *obfuscatedPWBuffer;
+
+ // The size of the obfuscated password should be the smallest multiple of
+ // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength.
+ obfuscatedPWLength = (((pwLength - 1) / kObfuscatedPasswordSizeMultiple) + 1) * kObfuscatedPasswordSizeMultiple;
+ obfuscatedPWBuffer = (char *) malloc(obfuscatedPWLength);
+
+ // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer
+ bcopy(pwAsUTF8String, obfuscatedPWBuffer, pwLength);
+
+ // Pad remainder of obfuscatedPWBuffer with random bytes
+ {
+ char *p;
+ char *endOfBuffer = obfuscatedPWBuffer + obfuscatedPWLength;
+
+ for (p = obfuscatedPWBuffer + pwLength; p < endOfBuffer; ++p)
+ *p = random() & 0x000000FF;
+ }
+
+ obfuscate(obfuscatedPWBuffer, obfuscatedPWLength);
+
+ int pwFile = open(kAutologinPWFilePath, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+ if (pwFile >= 0) {
+ size_t wrote = write(pwFile, obfuscatedPWBuffer, obfuscatedPWLength);
+ if (wrote == obfuscatedPWLength)
+ result = true;
+ close(pwFile);
+ }
+
+ chmod(kAutologinPWFilePath, S_IRUSR | S_IWUSR);
+ free(obfuscatedPWBuffer);
+ }
+ }
+
+ return result;
+}
OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) {
+ COUNTLEGACYAPI
SecTrustedApplicationRef itemPath;
SecAccessRef ourAccessRef = NULL;
OSStatus result = errSecParam;
+ if (userKeychainRef == NULL) {
+ // We don't have a specific user keychain, fall back
+ if (_SASetAutologinPW(password))
+ result = errSecSuccess;
+
+ return result;
+ }
+
CFDataRef masterKey = NULL;
result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password);
if (errSecSuccess != result) {
result = SecKeychainStash();
if (errSecSuccess != result) {
- if (NULL != masterKey) CFRelease(masterKey);
+ if (masterKey != NULL) CFRelease(masterKey);
return result;
}
CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- if ( noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath )
+ if (noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath)
CFArrayAppendValue(trustedApplications, itemPath);
- if ( trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) {
+ if (trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) {
if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) {
+ SecKeychainRef internalSystemKeychainRef = NULL;
if (NULL == systemKeychainRef) {
- SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &systemKeychainRef);
+ SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &internalSystemKeychainRef);
+ } else {
+ internalSystemKeychainRef = systemKeychainRef;
}
const void *queryKeys[] = { kSecClass,
const void *queryValues[] = { kSecClassGenericPassword,
CFSTR("com.apple.loginwindow.auto-login"),
username,
- systemKeychainRef,
+ internalSystemKeychainRef,
};
const void *updateKeys[] = { kSecAttrAccess,
const void *addValues[] = { kSecClassGenericPassword,
CFSTR("com.apple.loginwindow.auto-login"),
username,
- systemKeychainRef,
+ internalSystemKeychainRef,
ourAccessRef,
masterKey,
};
if (NULL != query) CFRelease(query);
if (NULL != update) CFRelease(update);
+
+ // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one
+ if (systemKeychainRef == NULL) CFRelease(internalSystemKeychainRef);
}
}
if (NULL != masterKey) CFRelease(masterKey);
if (NULL != trustedApplications) CFRelease(trustedApplications);
if (NULL != ourAccessRef) CFRelease(ourAccessRef);
- if (NULL != systemKeychainRef) CFRelease(systemKeychainRef);
return result;
}
+
+OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts)
+{
+ BEGIN_SECAPI
+
+ os_activity_t activity = os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
+ os_activity_scope(activity);
+ os_release(activity);
+
+ if(attempts) {
+ SecurityServer::ClientSession().getUserPromptAttempts(*attempts);
+ }
+
+ END_SECAPI
+}
+
+OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash,
+ SecKeychainRef userKeychain, CFStringRef password)
+{
+ COUNTLEGACYAPI
+ CFRef<CFStringRef> pwd;
+ OSStatus result;
+
+ if (password == NULL || CFStringGetLength(password) == 0) {
+ AuthorizationRef authorizationRef;
+ result = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorizationRef);
+ if (result != errAuthorizationSuccess) {
+ secnotice("SecKeychain", "failed to create authorization");
+ return result;
+ }
+
+ AuthorizationItem myItems = {"com.apple.ctk.pair", 0, NULL, 0};
+ AuthorizationRights myRights = {1, &myItems};
+
+ char pathName[PATH_MAX];
+ UInt32 pathLength = PATH_MAX;
+ result = SecKeychainGetPath(userKeychain, &pathLength, pathName);
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "failed to create authorization");
+ return result;
+ }
+
+ Boolean checkPwd = TRUE;
+ Boolean ignoreSession = TRUE;
+ AuthorizationItem envItems[] = {
+ {AGENT_HINT_KEYCHAIN_PATH, pathLength, pathName, 0},
+ {AGENT_HINT_KEYCHAIN_CHECK, sizeof(checkPwd), &checkPwd},
+ {AGENT_HINT_IGNORE_SESSION, sizeof(ignoreSession), &ignoreSession}
+ };
+
+ AuthorizationEnvironment environment = {3, envItems};
+ AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
+ result = AuthorizationCopyRights(authorizationRef, &myRights, &environment, flags, NULL);
+ secnotice("SecKeychain", "Authorization result: %d", (int)result);
+
+ if (result == errAuthorizationSuccess) {
+ AuthorizationItemSet *items;
+ result = AuthorizationCopyInfo(authorizationRef, kAuthorizationEnvironmentPassword, &items);
+ secnotice("SecKeychain", "Items copy result: %d", (int)result);
+ if (result == errAuthorizationSuccess) {
+ secnotice("SecKeychain", "Items count: %d", items->count);
+ if (items->count > 0) {
+ pwd = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)items->items[0].value, kCFStringEncodingUTF8);
+ if (pwd) {
+ secnotice("SecKeychain", "Got kcpass");
+ }
+ }
+ AuthorizationFreeItemSet(items);
+ }
+ }
+ AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
+ if (result != errAuthorizationSuccess) {
+ secnotice("SecKeychain", "did not get authorization to pair the card");
+ return result;
+ }
+ } else {
+ pwd.take(password);
+ }
+
+ if (!pwd) {
+ secnotice("SecKeychain", "did not get kcpass");
+ return errSecInternalComponent;
+ }
+
+ CFRef<CFDataRef> masterKey;
+ result = SecKeychainGetMasterKey(userKeychain, masterKey.take(), pwd);
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "Failed to get master key: %d", (int) result);
+ return result;
+ }
+
+ CFRef<CFDataRef> scBlob;
+ result = TokenLoginGetScBlob(wrapPubKeyHash, tokenID, pwd, scBlob.take());
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "Failed to get stash: %d", (int) result);
+ return result;
+ }
+
+ result = TokenLoginCreateLoginData(tokenID, pubKeyHash, wrapPubKeyHash, masterKey, scBlob);
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "Failed to create login data: %d", (int) result);
+ return result;
+ }
+
+ secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result);
+
+ // create SC KEK
+ // this might fail if KC password is different from user's password
+ uid_t uid = geteuid();
+ if (!uid) {
+ uid = getuid();
+ }
+ struct passwd *passwd = getpwuid(uid);
+ if (passwd) {
+ CFRef<CFStringRef> username = CFStringCreateWithCString(kCFAllocatorDefault, passwd->pw_name, kCFStringEncodingUTF8);
+ OSStatus kekRes = TKAddSecureToken(username, pwd, tokenID, wrapPubKeyHash);
+ if (kekRes != noErr) {
+ secnotice("SecKeychain", "Failed to register SC token: %d", (int) kekRes); // do not fail because KC functionality be still OK
+ }
+ } else {
+ secnotice("SecKeychain", "Unable to get name for uid %d", uid);
+ }
+ return result;
+}
+
+OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash)
+{
+ COUNTLEGACYAPI
+ OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash);
+ if (result != errSecSuccess) {
+ secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result);
+ }
+ return result;
+}