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