2 * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
18 #include <Security/SecKeychainAPIPriv.h>
19 #include <Security/SecKeychain.h>
20 #include <Security/cssmdata.h>
21 #include <Security/KCExceptions.h>
22 #include "SecBridge.h"
23 #include "CCallbackMgr.h"
28 SecKeychainGetTypeID(void)
32 return gTypes().keychain
.typeId
;
34 END_SECAPI1(_kCFRuntimeNotATypeID
)
39 SecKeychainGetVersion(UInt32
*returnVers
)
44 *returnVers
= 0x02028000;
50 SecKeychainOpen(const char *pathName
, SecKeychainRef
*keychainRef
)
54 RequiredParam(keychainRef
)=gTypes().keychain
.handle(*globals().storageManager
.make(pathName
));
61 SecKeychainCreate(const char *pathName
, UInt32 passwordLength
, const void *password
,
62 Boolean promptUser
, SecAccessRef initialAccess
, SecKeychainRef
*keychainRef
)
66 KCThrowParamErrIf_(!pathName
);
67 Keychain keychain
= globals().storageManager
.make(pathName
);
69 // @@@ the call to StorageManager::make above leaves keychain the the cache.
70 // If the create below fails we should probably remove it.
75 KCThrowParamErrIf_(!password
);
76 keychain
->create(passwordLength
, password
);
78 RequiredParam(keychainRef
)=gTypes().keychain
.handle(*keychain
);
85 SecKeychainDelete(SecKeychainRef keychainOrArray
)
89 StorageManager::KeychainList keychains
;
90 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
91 globals().storageManager
.remove(keychains
, true);
98 SecKeychainSetSettings(SecKeychainRef keychainRef
, const SecKeychainSettings
*newSettings
)
102 Keychain keychain
= Keychain::optional(keychainRef
);
103 if (newSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
)
105 UInt32 lockInterval
=newSettings
->lockInterval
;
106 bool lockOnSleep
=newSettings
->lockOnSleep
;
107 keychain
->setSettings(lockInterval
, lockOnSleep
);
115 SecKeychainCopySettings(SecKeychainRef keychainRef
, SecKeychainSettings
*outSettings
)
119 Keychain keychain
= Keychain::optional(keychainRef
);
120 if (outSettings
->version
==SEC_KEYCHAIN_SETTINGS_VERS1
)
125 keychain
->getSettings(lockInterval
, lockOnSleep
);
126 outSettings
->lockInterval
=lockInterval
;
127 outSettings
->lockOnSleep
=lockOnSleep
;
135 SecKeychainUnlock(SecKeychainRef keychainRef
, UInt32 passwordLength
, void *password
, Boolean usePassword
)
139 Keychain keychain
= Keychain::optional(keychainRef
);
142 keychain
->unlock(CssmData(password
,passwordLength
));
151 SecKeychainLock(SecKeychainRef keychainRef
)
155 Keychain keychain
= Keychain::optional(keychainRef
);
163 SecKeychainLockAll(void)
167 globals().storageManager
.lockAll();
174 SecKeychainCopyDefault(SecKeychainRef
*keychainRef
)
178 RequiredParam(keychainRef
)=gTypes().keychain
.handle(*globals().defaultKeychain
.keychain());
185 SecKeychainSetDefault(SecKeychainRef keychainRef
)
189 globals().defaultKeychain
.keychain(Keychain::optional(keychainRef
));
194 OSStatus
SecKeychainCopySearchList(CFArrayRef
* searchList
)
198 RequiredParam(searchList
);
199 StorageManager
&smr
= globals().storageManager
;
200 StorageManager::KeychainList keychainList
;
201 smr
.getSearchList(keychainList
);
202 *searchList
= smr
.convertFromKeychainList(keychainList
);
207 OSStatus
SecKeychainSetSearchList(CFArrayRef searchList
)
211 RequiredParam(searchList
);
212 StorageManager
&smr
= globals().storageManager
;
213 StorageManager::KeychainList keychainList
;
214 smr
.convertToKeychainList(searchList
, keychainList
);
215 smr
.setSearchList(keychainList
);
221 SecKeychainGetStatus(SecKeychainRef keychainRef
, SecKeychainStatus
*keychainStatus
)
225 RequiredParam(keychainStatus
) = (SecKeychainStatus
)Keychain::optional(keychainRef
)->status();
232 SecKeychainGetPath(SecKeychainRef keychainRef
, UInt32
* ioPathLength
, char *pathName
)
236 RequiredParam(pathName
);
238 const char *name
= Keychain::optional(keychainRef
)->name();
239 UInt32 nameLen
= strlen(name
);
240 if (nameLen
+1 > *ioPathLength
) // if the client's buffer is too small (including null-termination), throw
241 CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL
);
242 strncpy(pathName
, name
, nameLen
);
243 pathName
[nameLen
] = 0;
244 *ioPathLength
= nameLen
; // set the length.
252 SecKeychainListGetCount(void)
256 return globals().storageManager
.size();
264 SecKeychainListCopyKeychainAtIndex(UInt16 index
, SecKeychainRef
*keychainRef
)
268 KeychainCore::StorageManager
&smgr
=KeychainCore::globals().storageManager
;
269 RequiredParam(keychainRef
)=gTypes().keychain
.handle(*smgr
[index
]);
277 SecKeychainListRemoveKeychain(SecKeychainRef
*keychainRef
)
281 Required(keychainRef
);
282 Keychain keychain
= Keychain::optional(*keychainRef
);
283 StorageManager::KeychainList keychainList
;
284 keychainList
.push_back(keychain
);
285 globals().storageManager
.remove(keychainList
);
293 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef
, UInt32 itemID
, SecKeychainAttributeInfo
**info
)
297 Keychain keychain
= Keychain::optional(keychainRef
);
298 keychain
->getAttributeInfoForItemID(itemID
, info
);
305 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo
*info
)
309 KeychainImpl::freeAttributeInfo(info
);
316 SecKeychainAddCallback(SecKeychainCallback callbackFunction
, SecKeychainEventMask eventMask
, void* userContext
)
320 RequiredParam(callbackFunction
);
321 CCallbackMgr::AddCallback(callbackFunction
,eventMask
,userContext
);
328 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction
)
332 RequiredParam(callbackFunction
);
333 CCallbackMgr::RemoveCallback(callbackFunction
);
340 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
)
344 KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
);
345 // @@@ Get real itemClass
346 Item
item(kSecInternetPasswordItemClass
, 'aapl', passwordLength
, passwordData
);
348 if (serverName
&& serverNameLength
)
349 item
->setAttribute(Schema::attributeInfo(kSecServerItemAttr
),
350 CssmData(const_cast<void *>(reinterpret_cast<const void *>(serverName
)), serverNameLength
));
352 if (accountName
&& accountNameLength
)
354 CssmData
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
);
355 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
356 // @@@ We should probably leave setting of label up to lower level code.
357 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), account
);
360 if (securityDomain
&& securityDomainLength
)
361 item
->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr
),
362 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain
)), securityDomainLength
));
364 item
->setAttribute(Schema::attributeInfo(kSecPortItemAttr
), UInt32(port
));
365 item
->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr
), protocol
);
366 item
->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr
), authenticationType
);
368 if (path
&& pathLength
)
369 item
->setAttribute(Schema::attributeInfo(kSecPathItemAttr
),
370 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path
)), pathLength
));
372 Keychain::optional(keychainRef
)->add(item
);
374 *itemRef
= gTypes().item
.handle(*item
);
381 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
)
386 StorageManager::KeychainList keychains
;
387 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
388 KCCursor
cursor(keychains
, kSecInternetPasswordItemClass
, NULL
);
390 if (serverName
&& serverNameLength
)
392 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServerItemAttr
),
393 CssmData(const_cast<char *>(serverName
), serverNameLength
));
396 if (securityDomain
&& securityDomainLength
)
398 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecSecurityDomainItemAttr
),
399 CssmData (const_cast<char*>(securityDomain
), securityDomainLength
));
402 if (accountName
&& accountNameLength
)
404 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
),
405 CssmData (const_cast<char*>(accountName
), accountNameLength
));
410 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPortItemAttr
),
416 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecProtocolItemAttr
),
420 if (authenticationType
)
422 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAuthenticationTypeItemAttr
),
426 if (path
&& pathLength
)
428 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecPathItemAttr
), path
);
432 if (!cursor
->next(item
))
433 return errSecItemNotFound
;
435 // Get its data (only if necessary)
436 if (passwordData
|| passwordLength
)
438 CssmDataContainer outData
;
439 item
->getData(outData
);
440 *passwordLength
=outData
.length();
442 *passwordData
=outData
.data();
447 *itemRef
=gTypes().item
.handle(*item
);
454 SecKeychainAddGenericPassword(SecKeychainRef keychainRef
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32 passwordLength
, const void *passwordData
, SecKeychainItemRef
*itemRef
)
459 KCThrowParamErrIf_(passwordLength
!=0 && passwordData
==NULL
);
460 // @@@ Get real itemClass
461 Item
item(kSecGenericPasswordItemClass
, 'aapl', passwordLength
, passwordData
);
463 if (serviceName
&& serviceNameLength
)
464 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), CssmData(const_cast<void *>(reinterpret_cast<const void *>(serviceName
)), serviceNameLength
));
466 if (accountName
&& accountNameLength
)
468 CssmData
account(const_cast<void *>(reinterpret_cast<const void *>(accountName
)), accountNameLength
);
469 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
470 // @@@ We should probably leave setting of label up to lower level code.
471 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), account
);
474 Keychain::optional(keychainRef
)->add(item
);
476 *itemRef
= gTypes().item
.handle(*item
);
483 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray
, UInt32 serviceNameLength
, const char *serviceName
, UInt32 accountNameLength
, const char *accountName
, UInt32
*passwordLength
, void **passwordData
, SecKeychainItemRef
*itemRef
)
488 StorageManager::KeychainList keychains
;
489 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
490 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
492 if (serviceName
&& serviceNameLength
)
494 cursor
->add (CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
),
495 const_cast<char*>(serviceName
));
498 if (accountName
&& accountNameLength
)
500 cursor
->add (CSSM_DB_EQUAL
, Schema::attributeInfo(kSecAccountItemAttr
),
501 const_cast<char*>(accountName
));
505 if (!cursor
->next(item
))
506 return errSecItemNotFound
;
508 // Get its data (only if necessary)
509 if (passwordData
|| passwordLength
)
511 CssmDataContainer outData
;
512 item
->getData(outData
);
513 *passwordLength
=outData
.length();
515 *passwordData
=outData
.data();
520 *itemRef
=gTypes().item
.handle(*item
);
527 SecKeychainSetUserInteractionAllowed(Boolean state
)
531 globals().setUserInteractionAllowed(state
);
538 SecKeychainGetUserInteractionAllowed(Boolean
*state
)
542 Required(state
)=globals().getUserInteractionAllowed();
549 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef
, CSSM_DL_DB_HANDLE
*dldbHandle
)
553 RequiredParam(dldbHandle
);
555 Keychain keychain
= Keychain::optional(keychainRef
);
556 *dldbHandle
= keychain
->database()->handle();
563 SecKeychainGetCSPHandle(SecKeychainRef keychainRef
, CSSM_CSP_HANDLE
*cspHandle
)
567 RequiredParam(cspHandle
);
569 Keychain keychain
= Keychain::optional(keychainRef
);
570 *cspHandle
= keychain
->csp()->handle();
577 SecKeychainCopyAccess(SecKeychainRef keychainRef
, SecAccessRef
*accessRef
)
581 MacOSError::throwMe(unimpErr
);//%%%for now
588 SecKeychainSetAccess(SecKeychainRef keychainRef
, SecAccessRef accessRef
)
592 MacOSError::throwMe(unimpErr
);//%%%for now
598 #pragma mark ---- Private API ----
602 SecKeychainChangePassword(SecKeychainRef keychainRef
, UInt32 oldPasswordLength
, const void *oldPassword
, UInt32 newPasswordLength
, const void *newPassword
)
606 Keychain keychain
= Keychain::optional(keychainRef
);
607 keychain
->changePassphrase (oldPasswordLength
, oldPassword
, newPasswordLength
, newPassword
);
614 SecKeychainCopyLogin(SecKeychainRef
*keychainRef
)
618 // NOTE: operates on default Keychain! It shouldn't... we want to
619 // have code that operates of a login keychain.
620 RequiredParam(keychainRef
)=gTypes().keychain
.handle(*globals().defaultKeychain
.keychain());
627 SecKeychainLogin(UInt32 nameLength
, void* name
, UInt32 passwordLength
, void* password
)
631 globals().storageManager
.login(nameLength
, name
, passwordLength
, password
);
642 globals().storageManager
.logout();