2 * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecKeychain.h>
25 #include <Security/SecKeychainPriv.h>
26 #include <security_keychain/KCCursor.h>
27 #include <security_cdsa_utilities/cssmdata.h>
28 #include <security_cdsa_client/wrapkey.h>
29 #include <security_keychain/KCExceptions.h>
30 #include <securityd_client/ssblob.h>
31 #include <Security/SecAccess.h>
32 #include <Security/SecTrustedApplicationPriv.h>
33 #include "SecBridge.h"
34 #include "CCallbackMgr.h"
35 #include <security_cdsa_utilities/Schema.h>
36 #include <security_cdsa_client/mdsclient.h>
38 #include <os/activity.h>
39 #include <Security/AuthorizationTagsPriv.h>
40 #include <Security/Authorization.h>
41 #include "TokenLogin.h"
44 SecKeychainMDSInstall()
47 os_activity_t activity
= os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
48 os_activity_scope(activity
);
51 Security::MDSClient::Directory d
;
58 SecKeychainGetTypeID(void)
62 return gTypes().KeychainImpl
.typeID
;
64 END_SECAPI1(_kCFRuntimeNotATypeID
)
69 SecKeychainGetVersion(UInt32
*returnVers
)
74 *returnVers
= 0x02028000;
80 SecKeychainOpen(const char *pathName
, SecKeychainRef
*keychainRef
)
83 os_activity_t activity
= os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
84 os_activity_scope(activity
);
87 RequiredParam(keychainRef
)=globals().storageManager
.make(pathName
, false)->handle();
94 SecKeychainOpenWithGuid(const CSSM_GUID
*guid
, uint32 subserviceId
, uint32 subserviceType
, const char* dbName
,
95 const CSSM_NET_ADDRESS
*dbLocation
, SecKeychainRef
*keychain
)
98 os_activity_t activity
= os_activity_create("SecKeychainOpenWithGuid", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
99 os_activity_scope(activity
);
100 os_release(activity
);
102 // range check parameters
103 RequiredParam (guid
);
104 RequiredParam (dbName
);
106 // create a DLDbIdentifier that describes what should be opened
107 const CSSM_VERSION
*version
= NULL
;
108 const CssmSubserviceUid
ssuid(*guid
, version
, subserviceId
, subserviceType
);
109 DLDbIdentifier
dLDbIdentifier(ssuid
, dbName
, dbLocation
);
111 // make a keychain from the supplied info
112 RequiredParam(keychain
) = globals().storageManager
.makeKeychain(dLDbIdentifier
, false, false)->handle ();
119 SecKeychainCreate(const char *pathName
, UInt32 passwordLength
, const void *password
,
120 Boolean promptUser
, SecAccessRef initialAccess
, SecKeychainRef
*keychainRef
)
123 os_activity_t activity
= os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
124 os_activity_scope(activity
);
125 os_release(activity
);
127 KCThrowParamErrIf_(!pathName
);
128 Keychain keychain
= globals().storageManager
.make(pathName
, true, true);
130 // @@@ the call to StorageManager::make above leaves keychain the the cache.
131 // If the create below fails we should probably remove it.
136 KCThrowParamErrIf_(!password
);
137 keychain
->create(passwordLength
, password
);
140 RequiredParam(keychainRef
)=keychain
->handle();
147 SecKeychainDelete(SecKeychainRef keychainOrArray
)
150 os_activity_t activity
= os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
151 os_activity_scope(activity
);
152 os_release(activity
);
154 KCThrowIf_(!keychainOrArray
, errSecInvalidKeychain
);
155 StorageManager::KeychainList keychains
;
156 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
158 globals().storageManager
.remove(keychains
, true);
165 SecKeychainSetSettings(SecKeychainRef keychainRef
, const SecKeychainSettings
*newSettings
)
168 os_activity_t activity
= os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
169 os_activity_scope(activity
);
170 os_release(activity
);
172 Keychain keychain
= Keychain::optional(keychainRef
);
173 if (newSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
)
175 UInt32 lockInterval
=newSettings
->lockInterval
;
176 bool lockOnSleep
=newSettings
->lockOnSleep
;
177 keychain
->setSettings(lockInterval
, lockOnSleep
);
185 SecKeychainCopySettings(SecKeychainRef keychainRef
, SecKeychainSettings
*outSettings
)
188 os_activity_t activity
= os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
189 os_activity_scope(activity
);
190 os_release(activity
);
192 Keychain keychain
= Keychain::optional(keychainRef
);
193 if (outSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
)
198 keychain
->getSettings(lockInterval
, lockOnSleep
);
199 outSettings
->lockInterval
=lockInterval
;
200 outSettings
->lockOnSleep
=lockOnSleep
;
208 SecKeychainUnlock(SecKeychainRef keychainRef
, UInt32 passwordLength
, const void *password
, Boolean usePassword
)
211 os_activity_t activity
= os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
212 os_activity_scope(activity
);
213 os_release(activity
);
215 Keychain keychain
= Keychain::optional(keychainRef
);
218 keychain
->unlock(CssmData(const_cast<void *>(password
), passwordLength
));
227 SecKeychainLock(SecKeychainRef keychainRef
)
230 os_activity_t activity
= os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
231 os_activity_scope(activity
);
232 os_release(activity
);
234 Keychain keychain
= Keychain::optional(keychainRef
);
242 SecKeychainLockAll(void)
245 os_activity_t activity
= os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
246 os_activity_scope(activity
);
247 os_release(activity
);
249 globals().storageManager
.lockAll();
255 OSStatus
SecKeychainResetLogin(UInt32 passwordLength
, const void* password
, Boolean resetSearchList
)
258 os_activity_t activity
= os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
259 os_activity_scope(activity
);
260 os_release(activity
);
262 // Get the current user (using fallback method if necessary)
264 char* uName
= getenv("USER");
265 string userName
= uName
? uName
: "";
266 if ( userName
.length() == 0 )
268 uid_t uid
= geteuid();
269 if (!uid
) uid
= getuid();
270 struct passwd
*pw
= getpwuid(uid
); // fallback case...
272 userName
= pw
->pw_name
;
275 if ( userName
.length() == 0 ) // did we ultimately get one?
277 MacOSError::throwMe(errAuthorizationInternal
);
280 SecurityServer::ClientSession().resetKeyStorePassphrase(password
? CssmData(const_cast<void *>(password
), passwordLength
) : CssmData());
281 secwarning("SecKeychainResetLogin: reset AKS passphrase");
284 // Clear the plist and move aside (rename) the existing login.keychain
285 globals().storageManager
.resetKeychain(resetSearchList
);
287 // Create the login keychain without UI
288 globals().storageManager
.login((UInt32
)userName
.length(), userName
.c_str(), passwordLength
, password
, true);
290 // Set it as the default
291 Keychain keychain
= globals().storageManager
.loginKeychain();
292 globals().storageManager
.defaultKeychain(keychain
);
296 // Create the login keychain, prompting for password
297 // (implicitly calls resetKeychain, login, and defaultKeychain)
298 globals().storageManager
.makeLoginAuthUI(NULL
, true);
300 secwarning("SecKeychainResetLogin: reset osx keychain");
302 // Post a "list changed" event after a reset, so apps can refresh their list.
303 // Make sure we are not holding mLock when we post this event.
304 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent
);
311 SecKeychainCopyDefault(SecKeychainRef
*keychainRef
)
315 RequiredParam(keychainRef
)=globals().storageManager
.defaultKeychain()->handle();
322 SecKeychainSetDefault(SecKeychainRef keychainRef
)
325 os_activity_t activity
= os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
326 os_activity_scope(activity
);
327 os_release(activity
);
329 globals().storageManager
.defaultKeychain(Keychain::optional(keychainRef
));
334 OSStatus
SecKeychainCopySearchList(CFArrayRef
*searchList
)
337 os_activity_t activity
= os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
338 os_activity_scope(activity
);
339 os_release(activity
);
341 RequiredParam(searchList
);
342 StorageManager
&smr
= globals().storageManager
;
343 StorageManager::KeychainList keychainList
;
344 smr
.getSearchList(keychainList
);
345 *searchList
= smr
.convertFromKeychainList(keychainList
);
350 OSStatus
SecKeychainSetSearchList(CFArrayRef searchList
)
353 os_activity_t activity
= os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
354 os_activity_scope(activity
);
355 os_release(activity
);
357 RequiredParam(searchList
);
358 StorageManager
&smr
= globals().storageManager
;
359 StorageManager::KeychainList keychainList
;
360 smr
.convertToKeychainList(searchList
, keychainList
);
361 smr
.setSearchList(keychainList
);
366 OSStatus
SecKeychainCopyDomainDefault(SecPreferencesDomain domain
, SecKeychainRef
*keychainRef
)
369 os_activity_t activity
= os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
370 os_activity_scope(activity
);
371 os_release(activity
);
373 RequiredParam(keychainRef
)=globals().storageManager
.defaultKeychain(domain
)->handle();
378 OSStatus
SecKeychainSetDomainDefault(SecPreferencesDomain domain
, SecKeychainRef keychainRef
)
381 os_activity_t activity
= os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
382 os_activity_scope(activity
);
383 os_release(activity
);
385 globals().storageManager
.defaultKeychain(domain
, Keychain::optional(keychainRef
));
390 OSStatus
SecKeychainCopyDomainSearchList(SecPreferencesDomain domain
, CFArrayRef
*searchList
)
394 RequiredParam(searchList
);
395 StorageManager
&smr
= globals().storageManager
;
396 StorageManager::KeychainList keychainList
;
397 smr
.getSearchList(domain
, keychainList
);
398 *searchList
= smr
.convertFromKeychainList(keychainList
);
403 OSStatus
SecKeychainSetDomainSearchList(SecPreferencesDomain domain
, CFArrayRef searchList
)
406 os_activity_t activity
= os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
407 os_activity_scope(activity
);
408 os_release(activity
);
410 RequiredParam(searchList
);
411 StorageManager
&smr
= globals().storageManager
;
412 StorageManager::KeychainList keychainList
;
413 smr
.convertToKeychainList(searchList
, keychainList
);
414 smr
.setSearchList(domain
, keychainList
);
419 OSStatus
SecKeychainSetPreferenceDomain(SecPreferencesDomain domain
)
422 os_activity_t activity
= os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
423 os_activity_scope(activity
);
424 os_release(activity
);
426 globals().storageManager
.domain(domain
);
431 OSStatus
SecKeychainGetPreferenceDomain(SecPreferencesDomain
*domain
)
434 os_activity_t activity
= os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
435 os_activity_scope(activity
);
436 os_release(activity
);
438 *domain
= globals().storageManager
.domain();
445 SecKeychainGetStatus(SecKeychainRef keychainRef
, SecKeychainStatus
*keychainStatus
)
449 RequiredParam(keychainStatus
) = (SecKeychainStatus
)Keychain::optional(keychainRef
)->status();
456 SecKeychainGetPath(SecKeychainRef keychainRef
, UInt32
*ioPathLength
, char *pathName
)
460 RequiredParam(pathName
);
461 RequiredParam(ioPathLength
);
463 const char *name
= Keychain::optional(keychainRef
)->name();
464 UInt32 nameLen
= (UInt32
)strlen(name
);
465 UInt32 callersLen
= *ioPathLength
;
466 *ioPathLength
= nameLen
;
467 if (nameLen
+1 > callersLen
) // if the client's buffer is too small (including null-termination), throw
468 return errSecBufferTooSmall
;
469 strncpy(pathName
, name
, nameLen
);
470 pathName
[nameLen
] = 0;
471 *ioPathLength
= nameLen
; // set the length.
477 SecKeychainGetKeychainVersion(SecKeychainRef keychainRef
, UInt32
* version
)
481 RequiredParam(version
);
483 *version
= Keychain::optional(keychainRef
)->database()->dbBlobVersion();
489 SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain
, UInt32 version
, const char* masterKeyFilename
)
492 os_activity_t activity
= os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
493 os_activity_scope(activity
);
494 os_release(activity
);
496 RequiredParam(masterKeyFilename
);
497 Keychain kc
= Keychain::optional(keychain
);
499 SecurityServer::SystemKeychainKey
keychainKey(masterKeyFilename
);
500 if(keychainKey
.valid()) {
501 // We've managed to read the key; now, create credentials using it
502 string path
= kc
->name();
504 CssmClient::Key
keychainMasterKey(kc
->csp(), keychainKey
.key(), true);
505 CssmClient::AclFactory::MasterKeyUnlockCredentials
creds(keychainMasterKey
, Allocator::standard(Allocator::sensitive
));
507 // Attempt the migrate, using our master key as the ACL override
508 bool result
= kc
->keychainMigration(path
, kc
->database()->dbBlobVersion(), path
, version
, creds
.getAccessCredentials());
512 return (kc
->database()->dbBlobVersion() == version
? errSecSuccess
: errSecBadReq
);
523 SecKeychainListGetCount(void)
527 return globals().storageManager
.size();
535 SecKeychainListCopyKeychainAtIndex(UInt16 index
, SecKeychainRef
*keychainRef
)
539 KeychainCore::StorageManager
&smgr
=KeychainCore::globals().storageManager
;
540 RequiredParam(keychainRef
)=smgr
[index
]->handle();
548 SecKeychainListRemoveKeychain(SecKeychainRef
*keychainRef
)
552 Required(keychainRef
);
553 Keychain keychain
= Keychain::optional(*keychainRef
);
554 StorageManager::KeychainList keychainList
;
555 keychainList
.push_back(keychain
);
556 globals().storageManager
.remove(keychainList
);
564 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef
, UInt32 itemID
, SecKeychainAttributeInfo
**info
)
568 Keychain keychain
= Keychain::optional(keychainRef
);
569 keychain
->getAttributeInfoForItemID(itemID
, info
);
576 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo
*info
)
580 KeychainImpl::freeAttributeInfo(info
);
587 SecKeychainAddCallback(SecKeychainCallback callbackFunction
, SecKeychainEventMask eventMask
, void* userContext
)
590 os_activity_t activity
= os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
591 os_activity_scope(activity
);
592 os_release(activity
);
594 RequiredParam(callbackFunction
);
595 CCallbackMgr::AddCallback(callbackFunction
,eventMask
,userContext
);
602 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction
)
605 os_activity_t activity
= os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
606 os_activity_scope(activity
);
607 os_release(activity
);
609 RequiredParam(callbackFunction
);
610 CCallbackMgr::RemoveCallback(callbackFunction
);
616 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
)
619 os_activity_t activity
= os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
620 os_activity_scope(activity
);
621 os_release(activity
);
623 KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
);
624 // @@@ Get real itemClass
625 Item
item(kSecInternetPasswordItemClass
, 'aapl', passwordLength
, passwordData
, false);
627 if (serverName
&& serverNameLength
)
629 CssmData
server(const_cast<void *>(reinterpret_cast<const void *>(serverName
)), serverNameLength
);
630 item
->setAttribute(Schema::attributeInfo(kSecServerItemAttr
), server
);
631 // use server name as default label
632 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), server
);
635 if (accountName
&& accountNameLength
)
637 CssmData
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
);
638 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
641 if (securityDomain
&& securityDomainLength
)
642 item
->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr
),
643 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain
)), securityDomainLength
));
645 item
->setAttribute(Schema::attributeInfo(kSecPortItemAttr
), UInt32(port
));
646 item
->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr
), protocol
);
647 item
->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr
), authenticationType
);
649 if (path
&& pathLength
)
650 item
->setAttribute(Schema::attributeInfo(kSecPathItemAttr
),
651 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path
)), pathLength
));
653 Keychain keychain
= nil
;
656 keychain
= Keychain::optional(keychainRef
);
657 if ( !keychain
->exists() )
659 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
664 keychain
= globals().storageManager
.defaultKeychainUI(item
);
670 *itemRef
= item
->handle();
677 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
)
681 os_activity_t activity
= os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
682 os_activity_scope(activity
);
683 os_release(activity
);
685 StorageManager::KeychainList keychains
;
686 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
687 KCCursor
cursor(keychains
, kSecInternetPasswordItemClass
, NULL
);
689 if (serverName
&& serverNameLength
)
691 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServerItemAttr
),
692 CssmData(const_cast<char *>(serverName
), serverNameLength
));
695 if (securityDomain
&& securityDomainLength
)
697 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecSecurityDomainItemAttr
),
698 CssmData (const_cast<char*>(securityDomain
), securityDomainLength
));
701 if (accountName
&& accountNameLength
)
703 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
),
704 CssmData (const_cast<char*>(accountName
), accountNameLength
));
709 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPortItemAttr
),
715 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecProtocolItemAttr
),
719 if (authenticationType
)
721 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAuthenticationTypeItemAttr
),
725 if (path
&& pathLength
)
727 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPathItemAttr
), path
);
731 if (!cursor
->next(item
))
732 return errSecItemNotFound
;
734 // Get its data (only if necessary)
735 if (passwordData
|| passwordLength
)
737 CssmDataContainer outData
;
738 item
->getData(outData
);
739 if (passwordLength
) {
740 *passwordLength
=(UInt32
)outData
.length();
744 *passwordData
=outData
.data();
750 *itemRef
=item
->handle();
757 SecKeychainAddGenericPassword(SecKeychainRef keychainRef
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32 passwordLength
, const void *passwordData
, SecKeychainItemRef
*itemRef
)
760 os_activity_t activity
= os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
761 os_activity_scope(activity
);
762 os_release(activity
);
764 KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
);
765 // @@@ Get real itemClass
767 Item
item(kSecGenericPasswordItemClass
, 'aapl', passwordLength
, passwordData
, false);
769 if (serviceName
&& serviceNameLength
)
771 CssmData
service(const_cast<void *>(reinterpret_cast<const void *>(serviceName
)), serviceNameLength
);
772 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
);
773 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
);
776 if (accountName
&& accountNameLength
)
778 CssmData
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
);
779 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
782 Keychain keychain
= nil
;
785 keychain
= Keychain::optional(keychainRef
);
786 if ( !keychain
->exists() )
788 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
793 keychain
= globals().storageManager
.defaultKeychainUI(item
);
798 *itemRef
= item
->handle();
805 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32
*passwordLength
, void **passwordData
, SecKeychainItemRef
*itemRef
)
809 os_activity_t activity
= os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
810 os_activity_scope(activity
);
811 os_release(activity
);
813 StorageManager::KeychainList keychains
;
814 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
815 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
817 if (serviceName
&& serviceNameLength
)
819 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
),
820 CssmData(const_cast<char *>(serviceName
), serviceNameLength
));
823 if (accountName
&& accountNameLength
)
825 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
),
826 CssmData(const_cast<char *>(accountName
), accountNameLength
));
830 if (!cursor
->next(item
))
831 return errSecItemNotFound
;
833 // Get its data (only if necessary)
834 if (passwordData
|| passwordLength
)
836 CssmDataContainer outData
;
837 item
->getData(outData
);
838 if (passwordLength
) {
839 *passwordLength
=(UInt32
)outData
.length();
843 *passwordData
=outData
.data();
849 *itemRef
=item
->handle();
856 SecKeychainSetUserInteractionAllowed(Boolean state
)
860 globals().setUserInteractionAllowed(state
);
867 SecKeychainGetUserInteractionAllowed(Boolean
*state
)
871 Required(state
)=globals().getUserInteractionAllowed();
878 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef
, CSSM_DL_DB_HANDLE
*dldbHandle
)
881 os_activity_t activity
= os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
882 os_activity_scope(activity
);
883 os_release(activity
);
885 RequiredParam(dldbHandle
);
887 Keychain keychain
= Keychain::optional(keychainRef
);
888 *dldbHandle
= keychain
->database()->handle();
893 static ModuleNexus
<Mutex
> gSecReturnedKeychainCSPsMutex
;
894 static ModuleNexus
<std::set
<CssmClient::CSP
>> gSecReturnedKeychainCSPs
;
897 SecKeychainGetCSPHandle(SecKeychainRef keychainRef
, CSSM_CSP_HANDLE
*cspHandle
)
901 RequiredParam(cspHandle
);
903 Keychain keychain
= Keychain::optional(keychainRef
);
905 // Once we vend this handle, we can no longer delete this CSP object via RAII (and thus call CSSM_ModuleDetach on the CSP).
906 // Keep a global pointer to it to force the CSP to stay live forever.
907 CssmClient::CSP returnedKeychainCSP
= keychain
->csp();
909 StLock
<Mutex
> _(gSecReturnedKeychainCSPsMutex());
910 gSecReturnedKeychainCSPs().insert(returnedKeychainCSP
);
912 *cspHandle
= returnedKeychainCSP
->handle();
919 SecKeychainCopyAccess(SecKeychainRef keychainRef
, SecAccessRef
*accessRef
)
923 MacOSError::throwMe(errSecUnimplemented
);//%%%for now
930 SecKeychainSetAccess(SecKeychainRef keychainRef
, SecAccessRef accessRef
)
934 MacOSError::throwMe(errSecUnimplemented
);//%%%for now
940 #pragma mark ---- Private API ----
944 SecKeychainChangePassword(SecKeychainRef keychainRef
, UInt32 oldPasswordLength
, const void *oldPassword
, UInt32 newPasswordLength
, const void *newPassword
)
947 os_activity_t activity
= os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
948 os_activity_scope(activity
);
949 os_release(activity
);
951 Keychain keychain
= Keychain::optional(keychainRef
);
952 keychain
->changePassphrase (oldPasswordLength
, oldPassword
, newPasswordLength
, newPassword
);
959 SecKeychainCopyLogin(SecKeychainRef
*keychainRef
)
962 os_activity_t activity
= os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
963 os_activity_scope(activity
);
964 os_release(activity
);
966 RequiredParam(keychainRef
)=globals().storageManager
.loginKeychain()->handle();
973 SecKeychainLogin(UInt32 nameLength
, const void* name
, UInt32 passwordLength
, const void* password
)
976 os_activity_t activity
= os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
977 os_activity_scope(activity
);
978 os_release(activity
);
983 globals().storageManager
.login(nameLength
, name
, passwordLength
, password
, false);
985 globals().storageManager
.stashLogin();
988 catch (CommonError
&e
)
990 secnotice("KCLogin", "SecKeychainLogin failed: %d, password was%s supplied", (int)e
.osStatus(), password
?"":" not");
991 if (e
.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED
)
993 return errSecAuthFailed
;
1002 __secapiresult
=errSecInternalComponent
;
1004 secnotice("KCLogin", "SecKeychainLogin result: %d, password was%s supplied", (int)__secapiresult
, password
?"":" not");
1009 OSStatus
SecKeychainStash()
1012 os_activity_t activity
= os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1013 os_activity_scope(activity
);
1014 os_release(activity
);
1018 globals().storageManager
.stashKeychain();
1020 catch (CommonError
&e
)
1022 if (e
.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED
)
1024 return errSecAuthFailed
;
1028 return e
.osStatus();
1039 os_activity_t activity
= os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1040 os_activity_scope(activity
);
1041 os_release(activity
);
1043 globals().storageManager
.logout();
1048 /* (non-exported C utility routine) 'Makes' a keychain based on a full path
1050 static Keychain
make(const char *name
)
1052 return globals().storageManager
.make(name
);
1055 /* 'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs.
1056 Note this version doesn't take an accessRef or password.
1057 The "KC" create API takes a keychainRef...
1059 OSStatus
SecKeychainMakeFromFullPath(const char *fullPathName
, SecKeychainRef
*keychainRef
)
1062 RequiredParam(fullPathName
);
1063 RequiredParam(keychainRef
)=make(fullPathName
)->handle();
1068 /* Determines if the keychainRef is a valid keychain.
1070 OSStatus
SecKeychainIsValid(SecKeychainRef keychainRef
, Boolean
* isValid
)
1074 if (KeychainImpl::optional(keychainRef
)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL
)
1079 /* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs.
1081 OSStatus
SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef
)
1084 os_activity_t activity
= os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1085 os_activity_scope(activity
);
1086 os_release(activity
);
1087 StorageManager::KeychainList singleton
;
1088 singleton
.push_back(KeychainImpl::required(keychainRef
));
1089 globals().storageManager
.remove(singleton
);
1093 /* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs.
1095 OSStatus
SecKeychainCreateNew(SecKeychainRef keychainRef
, UInt32 passwordLength
, const char* inPassword
)
1098 os_activity_t activity
= os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1099 os_activity_scope(activity
);
1100 os_release(activity
);
1101 RequiredParam(inPassword
);
1102 KeychainImpl::required(keychainRef
)->create(passwordLength
, inPassword
);
1106 /* Modify a keychain so that it can be synchronized.
1108 OSStatus
SecKeychainRecodeKeychain(SecKeychainRef keychainRef
, CFArrayRef dbBlobArray
, CFDataRef extraData
)
1111 os_activity_t activity
= os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1112 os_activity_scope(activity
);
1113 os_release(activity
);
1115 // do error checking for required parameters
1116 RequiredParam(dbBlobArray
);
1117 RequiredParam(extraData
);
1119 const CssmData
extraCssmData(const_cast<UInt8
*>(CFDataGetBytePtr(extraData
)),
1120 CFDataGetLength(extraData
));
1122 CFIndex dbBlobArrayCount
= CFArrayGetCount(dbBlobArray
);
1123 size_t space
= sizeof(uint8
) + (dbBlobArrayCount
* sizeof(SecurityServer::DbHandle
));
1124 void *dataPtr
= (void*)malloc(space
);
1126 return errSecAllocate
;
1128 // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with.
1130 uint8
* sizePtr
= (uint8
*)dataPtr
;
1131 *sizePtr
= dbBlobArrayCount
;
1132 SecurityServer::DbHandle
*currDbHandle
= (SecurityServer::DbHandle
*)(sizePtr
+1);
1134 SecurityServer::ClientSession
ss(Allocator::standard(), Allocator::standard());
1135 for (index
=0; index
< dbBlobArrayCount
; index
++)
1137 CFDataRef cfBlobData
= (CFDataRef
)CFArrayGetValueAtIndex(dbBlobArray
, index
);
1138 const CssmData
thisKCData(const_cast<UInt8
*>(CFDataGetBytePtr(cfBlobData
)), CFDataGetLength(cfBlobData
));
1140 // Since it's to a DbHandle that's not on our disk (it came from user's iDisk),
1141 // it's OK to use the mIdentifier and access credentials of the keychain we're recoding.
1143 Keychain kc
= KeychainImpl::required(keychainRef
);
1144 *currDbHandle
= ss
.decodeDb(kc
->dlDbIdentifier(), kc
->defaultCredentials(), thisKCData
); /* returns a DbHandle (IPCDbHandle) */
1149 Keychain keychain
= Keychain::optional(keychainRef
);
1150 const CssmData
data(const_cast<UInt8
*>((uint8
*)dataPtr
), space
);
1151 Boolean recodeFailed
= false;
1153 int errCode
=errSecSuccess
;
1157 keychain
->recode(data
, extraCssmData
);
1159 catch (MacOSError e
)
1161 errCode
= e
.osStatus();
1162 recodeFailed
= true;
1164 catch (UnixError ue
)
1166 errCode
= ue
.unixError();
1169 currDbHandle
= (SecurityServer::DbHandle
*)(sizePtr
+1);
1170 for (index
=0; index
< dbBlobArrayCount
; index
++)
1172 ss
.releaseDb(*currDbHandle
);
1186 OSStatus
SecKeychainCopySignature(SecKeychainRef keychainRef
, CFDataRef
*keychainSignature
)
1189 os_activity_t activity
= os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1190 os_activity_scope(activity
);
1191 os_release(activity
);
1193 // do error checking for required parameters
1194 RequiredParam(keychainSignature
);
1196 // make a keychain object "wrapper" for this keychain ref
1197 Keychain keychain
= Keychain::optional(keychainRef
);
1198 CssmAutoData
data(keychain
->database()->allocator());
1199 keychain
->copyBlob(data
.get());
1201 // get the cssmDBBlob
1202 const SecurityServer::DbBlob
*cssmDBBlob
=
1203 data
.get().interpretedAs
<const SecurityServer::DbBlob
>();
1205 // convert from CDSA standards to CF standards
1206 *keychainSignature
= CFDataCreate(kCFAllocatorDefault
,
1207 cssmDBBlob
->randomSignature
.bytes
,
1208 sizeof(SecurityServer::DbBlob::Signature
));
1213 OSStatus
SecKeychainCopyBlob(SecKeychainRef keychainRef
, CFDataRef
*dbBlob
)
1216 os_activity_t activity
= os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1217 os_activity_scope(activity
);
1218 os_release(activity
);
1220 // do error checking for required parameters
1221 RequiredParam(dbBlob
);
1223 // make a keychain object "wrapper" for this keychain ref
1224 Keychain keychain
= Keychain::optional(keychainRef
);
1225 CssmAutoData
data(keychain
->database()->allocator());
1226 keychain
->copyBlob(data
.get());
1228 // convert from CDSA standards to CF standards
1229 *dbBlob
= CFDataCreate(kCFAllocatorDefault
, data
, data
.length());
1234 // make a new keychain with pre-existing secrets
1235 OSStatus
SecKeychainCreateWithBlob(const char* fullPathName
, CFDataRef dbBlob
, SecKeychainRef
*kcRef
)
1238 os_activity_t activity
= os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1239 os_activity_scope(activity
);
1240 os_release(activity
);
1242 KCThrowParamErrIf_(!fullPathName
);
1243 KCThrowParamErrIf_(!dbBlob
);
1245 Keychain keychain
= globals().storageManager
.make(fullPathName
);
1247 CssmData
blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob
)), CFDataGetLength(dbBlob
));
1249 // @@@ the call to StorageManager::make above leaves keychain the the cache.
1250 // If the create below fails we should probably remove it.
1251 keychain
->createWithBlob(blob
);
1253 RequiredParam(kcRef
)=keychain
->handle();
1260 // add a non-file based DB to the keychain list
1261 OSStatus
SecKeychainAddDBToKeychainList (SecPreferencesDomain domain
, const char* dbName
,
1262 const CSSM_GUID
*guid
, uint32 subServiceType
)
1265 os_activity_t activity
= os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1266 os_activity_scope(activity
);
1267 os_release(activity
);
1269 RequiredParam(dbName
);
1270 StorageManager
&smr
= globals().storageManager
;
1271 smr
.addToDomainList(domain
, dbName
, *guid
, subServiceType
);
1276 // determine if a non-file based DB is in the keychain list
1277 OSStatus
SecKeychainDBIsInKeychainList (SecPreferencesDomain domain
, const char* dbName
,
1278 const CSSM_GUID
*guid
, uint32 subServiceType
)
1281 RequiredParam(dbName
);
1282 StorageManager
&smr
= globals().storageManager
;
1283 smr
.isInDomainList(domain
, dbName
, *guid
, subServiceType
);
1287 // remove a non-file based DB from the keychain list
1288 OSStatus
SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain
, const char* dbName
,
1289 const CSSM_GUID
*guid
, uint32 subServiceType
)
1292 os_activity_t activity
= os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1293 os_activity_scope(activity
);
1294 os_release(activity
);
1295 RequiredParam(dbName
);
1296 StorageManager
&smr
= globals().storageManager
;
1297 smr
.removeFromDomainList(domain
, dbName
, *guid
, subServiceType
);
1302 // set server mode -- must be called before any other Sec* etc. call
1303 void SecKeychainSetServerMode()
1310 OSStatus
SecKeychainSetBatchMode (SecKeychainRef kcRef
, Boolean mode
, Boolean rollback
)
1313 os_activity_t activity
= os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1314 os_activity_scope(activity
);
1315 os_release(activity
);
1316 RequiredParam(kcRef
);
1317 Keychain keychain
= Keychain::optional(kcRef
);
1318 keychain
->setBatchMode(mode
, rollback
);
1324 OSStatus
SecKeychainCleanupHandles()
1327 END_SECAPI
// which causes the handle cache cleanup routine to run
1330 OSStatus
SecKeychainVerifyKeyStorePassphrase(uint32_t retries
)
1333 os_activity_t activity
= os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1334 os_activity_scope(activity
);
1335 os_release(activity
);
1336 SecurityServer::ClientSession().verifyKeyStorePassphrase(retries
);
1340 OSStatus
SecKeychainChangeKeyStorePassphrase()
1343 os_activity_t activity
= os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1344 os_activity_scope(activity
);
1345 os_release(activity
);
1346 SecurityServer::ClientSession().changeKeyStorePassphrase();
1350 static OSStatus
SecKeychainGetMasterKey(SecKeychainRef userKeychainRef
, CFDataRef
*masterKey
, CFStringRef password
)
1353 os_activity_t activity
= os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1354 os_activity_scope(activity
);
1355 os_release(activity
);
1357 // make a keychain object "wrapper" for this keychain ref
1358 Keychain keychain
= Keychain::optional(userKeychainRef
);
1360 CssmClient::Db db
= keychain
->database();
1362 // create the keychain, using appropriate credentials
1363 Allocator
&alloc
= db
->allocator();
1364 AutoCredentials
cred(alloc
); // will leak, but we're quitting soon :-)
1366 char passphrase
[1024];
1367 CFStringGetCString(password
, passphrase
, sizeof(passphrase
), kCFStringEncodingUTF8
);
1369 // use this passphrase
1370 cred
+= TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
,
1371 new(alloc
) ListElement(CSSM_SAMPLE_TYPE_PASSWORD
),
1372 new(alloc
) ListElement(StringData(passphrase
)));
1373 db
->authenticate(CSSM_DB_ACCESS_READ
, &cred
);
1375 CSSM_DL_DB_HANDLE dlDb
= db
->handle();
1376 CssmData dlDbData
= CssmData::wrap(dlDb
);
1378 KeySpec
spec(CSSM_KEYUSE_ANY
,
1379 CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
);
1381 DeriveKey
derive(keychain
->csp(), CSSM_ALGID_KEYCHAIN_KEY
, CSSM_ALGID_3DES_3KEY
, 3 * 64);
1382 derive(&dlDbData
, spec
, refKey
);
1384 // now extract the raw keybits
1386 WrapKey
wrap(keychain
->csp(), CSSM_ALGID_NONE
);
1387 wrap(refKey
, rawKey
);
1389 *masterKey
= CFDataCreate(kCFAllocatorDefault
, rawKey
.keyData(), rawKey
.length());
1394 static const char *kAutologinPWFilePath
= "/etc/kcpassword";
1395 static const uint32_t kObfuscatedPasswordSizeMultiple
= 12;
1396 static const uint32_t buffer_size
= 512;
1397 static const uint8_t kObfuscationKey
[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f};
1399 static void obfuscate(void *buffer
, size_t bufferLength
)
1401 uint8_t *pBuf
= (uint8_t *) buffer
;
1402 const uint8_t *pKey
= kObfuscationKey
, *eKey
= pKey
+ sizeof( kObfuscationKey
);
1404 while (bufferLength
--) {
1405 *pBuf
= *pBuf
^ *pKey
;
1409 pKey
= kObfuscationKey
;
1413 static bool _SASetAutologinPW(CFStringRef inAutologinPW
)
1415 bool result
= false;
1418 // Delete the kcpassword file if it exists already
1419 if (stat(kAutologinPWFilePath
, &sb
) == 0)
1420 unlink( kAutologinPWFilePath
);
1422 // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off.
1423 if (inAutologinPW
!= NULL
) {
1424 char buffer
[buffer_size
];
1425 const char *pwAsUTF8String
= CFStringGetCStringPtr(inAutologinPW
, kCFStringEncodingUTF8
);
1426 if (pwAsUTF8String
== NULL
) {
1427 if (CFStringGetCString(inAutologinPW
, buffer
, buffer_size
, kCFStringEncodingUTF8
)) pwAsUTF8String
= buffer
;
1430 if (pwAsUTF8String
!= NULL
) {
1431 size_t pwLength
= strlen(pwAsUTF8String
) + 1;
1432 size_t obfuscatedPWLength
;
1433 char *obfuscatedPWBuffer
;
1435 // The size of the obfuscated password should be the smallest multiple of
1436 // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength.
1437 obfuscatedPWLength
= (((pwLength
- 1) / kObfuscatedPasswordSizeMultiple
) + 1) * kObfuscatedPasswordSizeMultiple
;
1438 obfuscatedPWBuffer
= (char *) malloc(obfuscatedPWLength
);
1440 // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer
1441 bcopy(pwAsUTF8String
, obfuscatedPWBuffer
, pwLength
);
1443 // Pad remainder of obfuscatedPWBuffer with random bytes
1446 char *endOfBuffer
= obfuscatedPWBuffer
+ obfuscatedPWLength
;
1448 for (p
= obfuscatedPWBuffer
+ pwLength
; p
< endOfBuffer
; ++p
)
1449 *p
= random() & 0x000000FF;
1452 obfuscate(obfuscatedPWBuffer
, obfuscatedPWLength
);
1454 int pwFile
= open(kAutologinPWFilePath
, O_CREAT
| O_WRONLY
| O_NOFOLLOW
, S_IRUSR
| S_IWUSR
);
1456 size_t wrote
= write(pwFile
, obfuscatedPWBuffer
, obfuscatedPWLength
);
1457 if (wrote
== obfuscatedPWLength
)
1462 chmod(kAutologinPWFilePath
, S_IRUSR
| S_IWUSR
);
1463 free(obfuscatedPWBuffer
);
1470 OSStatus
SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef
, SecKeychainRef systemKeychainRef
, CFStringRef username
, CFStringRef password
) {
1471 SecTrustedApplicationRef itemPath
;
1472 SecAccessRef ourAccessRef
= NULL
;
1474 OSStatus result
= errSecParam
;
1476 if (userKeychainRef
== NULL
) {
1477 // We don't have a specific user keychain, fall back
1478 if (_SASetAutologinPW(password
))
1479 result
= errSecSuccess
;
1484 CFDataRef masterKey
= NULL
;
1485 result
= SecKeychainGetMasterKey(userKeychainRef
, &masterKey
, password
);
1486 if (errSecSuccess
!= result
) {
1490 result
= SecKeychainStash();
1491 if (errSecSuccess
!= result
) {
1492 if (masterKey
!= NULL
) CFRelease(masterKey
);
1496 CFMutableArrayRef trustedApplications
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1497 if (noErr
== SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL
, &itemPath
) && itemPath
)
1498 CFArrayAppendValue(trustedApplications
, itemPath
);
1500 if (trustedApplications
&& (CFArrayGetCount(trustedApplications
) > 0)) {
1501 if (errSecSuccess
== (result
= SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications
, &ourAccessRef
))) {
1502 SecKeychainRef internalSystemKeychainRef
= NULL
;
1503 if (NULL
== systemKeychainRef
) {
1504 SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &internalSystemKeychainRef
);
1506 internalSystemKeychainRef
= systemKeychainRef
;
1509 const void *queryKeys
[] = { kSecClass
,
1514 const void *queryValues
[] = { kSecClassGenericPassword
,
1515 CFSTR("com.apple.loginwindow.auto-login"),
1517 internalSystemKeychainRef
,
1520 const void *updateKeys
[] = { kSecAttrAccess
,
1523 const void *updateValues
[] = { ourAccessRef
,
1527 CFDictionaryRef query
= CFDictionaryCreate(kCFAllocatorDefault
, queryKeys
, queryValues
, sizeof(queryValues
)/sizeof(*queryValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1528 CFDictionaryRef update
= CFDictionaryCreate(kCFAllocatorDefault
, updateKeys
, updateValues
, sizeof(updateValues
)/sizeof(*updateValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1530 result
= SecItemUpdate(query
, update
);
1532 if (errSecSuccess
!= result
) {
1533 const void *addKeys
[] = { kSecClass
,
1540 const void *addValues
[] = { kSecClassGenericPassword
,
1541 CFSTR("com.apple.loginwindow.auto-login"),
1543 internalSystemKeychainRef
,
1548 CFDictionaryRef add
= CFDictionaryCreate(kCFAllocatorDefault
, addKeys
, addValues
, sizeof(addValues
)/sizeof(*addValues
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1549 result
= SecItemAdd(add
, NULL
);
1550 if (NULL
!= add
) CFRelease(add
);
1553 if (NULL
!= query
) CFRelease(query
);
1554 if (NULL
!= update
) CFRelease(update
);
1556 // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one
1557 if (systemKeychainRef
== NULL
) CFRelease(internalSystemKeychainRef
);
1561 if (NULL
!= masterKey
) CFRelease(masterKey
);
1562 if (NULL
!= trustedApplications
) CFRelease(trustedApplications
);
1563 if (NULL
!= ourAccessRef
) CFRelease(ourAccessRef
);
1568 OSStatus
SecKeychainGetUserPromptAttempts(uint32_t * attempts
)
1571 os_activity_t activity
= os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
1572 os_activity_scope(activity
);
1573 os_release(activity
);
1576 SecurityServer::ClientSession().getUserPromptAttempts(*attempts
);
1582 OSStatus
SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash
, CFStringRef tokenID
, CFDataRef wrapPubKeyHash
,
1583 SecKeychainRef userKeychain
, CFStringRef password
)
1585 CFRef
<CFStringRef
> pwd
;
1588 if (password
== NULL
|| CFStringGetLength(password
) == 0) {
1589 AuthorizationRef authorizationRef
;
1590 result
= AuthorizationCreate(NULL
, NULL
, kAuthorizationFlagDefaults
, &authorizationRef
);
1591 if (result
!= errAuthorizationSuccess
) {
1592 secnotice("SecKeychain", "failed to create authorization");
1596 AuthorizationItem myItems
= {"com.apple.ctk.pair", 0, NULL
, 0};
1597 AuthorizationRights myRights
= {1, &myItems
};
1598 AuthorizationRights
*authorizedRights
= NULL
;
1600 char pathName
[PATH_MAX
];
1601 UInt32 pathLength
= PATH_MAX
;
1602 result
= SecKeychainGetPath(userKeychain
, &pathLength
, pathName
);
1603 if (result
!= errSecSuccess
) {
1604 secnotice("SecKeychain", "failed to create authorization");
1608 Boolean checkPwd
= TRUE
;
1609 Boolean ignoreSession
= TRUE
;
1610 AuthorizationItem envItems
[] = {
1611 {AGENT_HINT_KEYCHAIN_PATH
, pathLength
, pathName
, 0},
1612 {AGENT_HINT_KEYCHAIN_CHECK
, sizeof(checkPwd
), &checkPwd
},
1613 {AGENT_HINT_IGNORE_SESSION
, sizeof(ignoreSession
), &ignoreSession
}
1616 AuthorizationEnvironment environment
= {3, envItems
};
1617 AuthorizationFlags flags
= kAuthorizationFlagDefaults
| kAuthorizationFlagInteractionAllowed
| kAuthorizationFlagExtendRights
;
1618 result
= AuthorizationCopyRights(authorizationRef
, &myRights
, &environment
, flags
, &authorizedRights
);
1619 if (authorizedRights
)
1620 AuthorizationFreeItemSet(authorizedRights
);
1622 if (result
== errAuthorizationSuccess
) {
1623 AuthorizationItemSet
*items
;
1624 result
= AuthorizationCopyInfo(authorizationRef
, kAuthorizationEnvironmentPassword
, &items
);
1625 if (result
== errAuthorizationSuccess
) {
1626 if (items
->count
> 0) {
1627 pwd
= CFStringCreateWithCString(kCFAllocatorDefault
, (const char *)items
->items
[0].value
, kCFStringEncodingUTF8
);
1629 AuthorizationFreeItemSet(items
);
1632 AuthorizationFree(authorizationRef
, kAuthorizationFlagDefaults
);
1633 if (result
!= errAuthorizationSuccess
) {
1634 secnotice("SecKeychain", "did not get authorization to pair the card");
1642 secnotice("SecKeychain", "did not get kcpass");
1643 return errSecInternalComponent
;
1646 CFRef
<CFDataRef
> masterKey
;
1647 result
= SecKeychainGetMasterKey(userKeychain
, masterKey
.take(), pwd
);
1648 if (result
!= errSecSuccess
) {
1649 secnotice("SecKeychain", "Failed to get master key: %d", (int) result
);
1653 CFRef
<CFDataRef
> scBlob
;
1654 result
= TokenLoginGetScBlob(wrapPubKeyHash
, tokenID
, pwd
, scBlob
.take());
1655 if (result
!= errSecSuccess
) {
1656 secnotice("SecKeychain", "Failed to get stash: %d", (int) result
);
1660 result
= TokenLoginCreateLoginData(tokenID
, pubKeyHash
, wrapPubKeyHash
, masterKey
, scBlob
);
1661 if (result
!= errSecSuccess
) {
1662 secnotice("SecKeychain", "Failed to create login data: %d", (int) result
);
1666 secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result
);
1670 OSStatus
SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash
)
1672 OSStatus result
= TokenLoginDeleteUnlockData(pubKeyHash
);
1673 if (result
!= errSecSuccess
) {
1674 secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result
);