]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/SecKeychain.cpp
Security-55163.44.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 noErr;
51
52 *returnVers = 0x02028000;
53 return noErr;
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(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 // Post a "list changed" event after a reset, so apps can refresh their list.
246 // Make sure we are not holding mLock when we post this event.
247 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
248
249 END_SECAPI
250 }
251
252 OSStatus
253 SecKeychainCopyDefault(SecKeychainRef *keychainRef)
254 {
255 BEGIN_SECAPI
256
257 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain()->handle();
258
259 END_SECAPI
260 }
261
262
263 OSStatus
264 SecKeychainSetDefault(SecKeychainRef keychainRef)
265 {
266 BEGIN_SECAPI
267
268 globals().storageManager.defaultKeychain(Keychain::optional(keychainRef));
269
270 END_SECAPI
271 }
272
273 OSStatus SecKeychainCopySearchList(CFArrayRef *searchList)
274 {
275 BEGIN_SECAPI
276
277 RequiredParam(searchList);
278 StorageManager &smr = globals().storageManager;
279 StorageManager::KeychainList keychainList;
280 smr.getSearchList(keychainList);
281 *searchList = smr.convertFromKeychainList(keychainList);
282
283 END_SECAPI
284 }
285
286 OSStatus SecKeychainSetSearchList(CFArrayRef searchList)
287 {
288 BEGIN_SECAPI
289
290 RequiredParam(searchList);
291 StorageManager &smr = globals().storageManager;
292 StorageManager::KeychainList keychainList;
293 smr.convertToKeychainList(searchList, keychainList);
294 smr.setSearchList(keychainList);
295
296 END_SECAPI
297 }
298
299 OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef)
300 {
301 BEGIN_SECAPI
302
303 RequiredParam(keychainRef)=globals().storageManager.defaultKeychain(domain)->handle();
304
305 END_SECAPI
306 }
307
308 OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef)
309 {
310 BEGIN_SECAPI
311
312 globals().storageManager.defaultKeychain(domain, Keychain::optional(keychainRef));
313
314 END_SECAPI
315 }
316
317 OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef *searchList)
318 {
319 BEGIN_SECAPI
320
321 RequiredParam(searchList);
322 StorageManager &smr = globals().storageManager;
323 StorageManager::KeychainList keychainList;
324 smr.getSearchList(domain, keychainList);
325 *searchList = smr.convertFromKeychainList(keychainList);
326
327 END_SECAPI
328 }
329
330 OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList)
331 {
332 BEGIN_SECAPI
333
334 RequiredParam(searchList);
335 StorageManager &smr = globals().storageManager;
336 StorageManager::KeychainList keychainList;
337 smr.convertToKeychainList(searchList, keychainList);
338 smr.setSearchList(domain, keychainList);
339
340 END_SECAPI
341 }
342
343 OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain)
344 {
345 BEGIN_SECAPI
346
347 globals().storageManager.domain(domain);
348
349 END_SECAPI
350 }
351
352 OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain)
353 {
354 BEGIN_SECAPI
355
356 *domain = globals().storageManager.domain();
357
358 END_SECAPI
359 }
360
361
362 OSStatus
363 SecKeychainGetStatus(SecKeychainRef keychainRef, SecKeychainStatus *keychainStatus)
364 {
365 BEGIN_SECAPI
366
367 RequiredParam(keychainStatus) = (SecKeychainStatus)Keychain::optional(keychainRef)->status();
368
369 END_SECAPI
370 }
371
372
373 OSStatus
374 SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathName)
375 {
376 BEGIN_SECAPI
377
378 RequiredParam(pathName);
379 RequiredParam(ioPathLength);
380
381 const char *name = Keychain::optional(keychainRef)->name();
382 UInt32 nameLen = strlen(name);
383 UInt32 callersLen = *ioPathLength;
384 *ioPathLength = nameLen;
385 if (nameLen+1 > callersLen) // if the client's buffer is too small (including null-termination), throw
386 return errSecBufferTooSmall;
387 strncpy(pathName, name, nameLen);
388 pathName[nameLen] = 0;
389 *ioPathLength = nameLen; // set the length.
390
391 END_SECAPI
392 }
393
394
395 // @@@ Deprecated
396 UInt16
397 SecKeychainListGetCount(void)
398 {
399 BEGIN_SECAPI
400
401 return globals().storageManager.size();
402
403 END_SECAPI1(0)
404 }
405
406
407 // @@@ Deprecated
408 OSStatus
409 SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef)
410 {
411 BEGIN_SECAPI
412
413 KeychainCore::StorageManager &smgr=KeychainCore::globals().storageManager;
414 RequiredParam(keychainRef)=smgr[index]->handle();
415
416 END_SECAPI
417 }
418
419
420 // @@@ Deprecated
421 OSStatus
422 SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef)
423 {
424 BEGIN_SECAPI
425
426 Required(keychainRef);
427 Keychain keychain = Keychain::optional(*keychainRef);
428 StorageManager::KeychainList keychainList;
429 keychainList.push_back(keychain);
430 globals().storageManager.remove(keychainList);
431 *keychainRef = NULL;
432
433 END_SECAPI
434 }
435
436
437 OSStatus
438 SecKeychainAttributeInfoForItemID(SecKeychainRef keychainRef, UInt32 itemID, SecKeychainAttributeInfo **info)
439 {
440 BEGIN_SECAPI
441
442 Keychain keychain = Keychain::optional(keychainRef);
443 keychain->getAttributeInfoForItemID(itemID, info);
444
445 END_SECAPI
446 }
447
448
449 OSStatus
450 SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info)
451 {
452 BEGIN_SECAPI
453
454 KeychainImpl::freeAttributeInfo(info);
455
456 END_SECAPI
457 }
458
459
460 pascal OSStatus
461 SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext)
462 {
463 BEGIN_SECAPI
464
465 RequiredParam(callbackFunction);
466 CCallbackMgr::AddCallback(callbackFunction,eventMask,userContext);
467
468 END_SECAPI
469 }
470
471
472 OSStatus
473 SecKeychainRemoveCallback(SecKeychainCallback callbackFunction)
474 {
475 BEGIN_SECAPI
476
477 RequiredParam(callbackFunction);
478 CCallbackMgr::RemoveCallback(callbackFunction);
479
480 END_SECAPI
481 }
482
483 OSStatus
484 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)
485 {
486 BEGIN_SECAPI
487
488 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
489 // @@@ Get real itemClass
490 Item item(kSecInternetPasswordItemClass, 'aapl', passwordLength, passwordData, false);
491
492 if (serverName && serverNameLength)
493 {
494 CssmData server(const_cast<void *>(reinterpret_cast<const void *>(serverName)), serverNameLength);
495 item->setAttribute(Schema::attributeInfo(kSecServerItemAttr), server);
496 // use server name as default label
497 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), server);
498 }
499
500 if (accountName && accountNameLength)
501 {
502 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
503 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
504 }
505
506 if (securityDomain && securityDomainLength)
507 item->setAttribute(Schema::attributeInfo(kSecSecurityDomainItemAttr),
508 CssmData(const_cast<void *>(reinterpret_cast<const void *>(securityDomain)), securityDomainLength));
509
510 item->setAttribute(Schema::attributeInfo(kSecPortItemAttr), UInt32(port));
511 item->setAttribute(Schema::attributeInfo(kSecProtocolItemAttr), protocol);
512 item->setAttribute(Schema::attributeInfo(kSecAuthenticationTypeItemAttr), authenticationType);
513
514 if (path && pathLength)
515 item->setAttribute(Schema::attributeInfo(kSecPathItemAttr),
516 CssmData(const_cast<void *>(reinterpret_cast<const void *>(path)), pathLength));
517
518 Keychain keychain = nil;
519 try
520 {
521 keychain = Keychain::optional(keychainRef);
522 if ( !keychain->exists() )
523 {
524 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
525 }
526 }
527 catch(...)
528 {
529 keychain = globals().storageManager.defaultKeychainUI(item);
530 }
531
532 keychain->add(item);
533
534 if (itemRef)
535 *itemRef = item->handle();
536
537 END_SECAPI
538 }
539
540
541 OSStatus
542 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)
543
544 {
545 BEGIN_SECAPI
546
547 StorageManager::KeychainList keychains;
548 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
549 KCCursor cursor(keychains, kSecInternetPasswordItemClass, NULL);
550
551 if (serverName && serverNameLength)
552 {
553 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServerItemAttr),
554 CssmData(const_cast<char *>(serverName), serverNameLength));
555 }
556
557 if (securityDomain && securityDomainLength)
558 {
559 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecSecurityDomainItemAttr),
560 CssmData (const_cast<char*>(securityDomain), securityDomainLength));
561 }
562
563 if (accountName && accountNameLength)
564 {
565 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
566 CssmData (const_cast<char*>(accountName), accountNameLength));
567 }
568
569 if (port)
570 {
571 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPortItemAttr),
572 UInt32(port));
573 }
574
575 if (protocol)
576 {
577 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecProtocolItemAttr),
578 protocol);
579 }
580
581 if (authenticationType)
582 {
583 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAuthenticationTypeItemAttr),
584 authenticationType);
585 }
586
587 if (path && pathLength)
588 {
589 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecPathItemAttr), path);
590 }
591
592 Item item;
593 if (!cursor->next(item))
594 return errSecItemNotFound;
595
596 // Get its data (only if necessary)
597 if (passwordData || passwordLength)
598 {
599 CssmDataContainer outData;
600 item->getData(outData);
601 *passwordLength=outData.length();
602 outData.Length=0;
603 *passwordData=outData.data();
604 outData.Data=NULL;
605 }
606
607 if (itemRef)
608 *itemRef=item->handle();
609
610 END_SECAPI
611 }
612
613
614 OSStatus
615 SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef)
616 {
617 BEGIN_SECAPI
618
619 KCThrowParamErrIf_(passwordLength!=0 && passwordData==NULL);
620 // @@@ Get real itemClass
621
622 Item item(kSecGenericPasswordItemClass, 'aapl', passwordLength, passwordData, false);
623
624 if (serviceName && serviceNameLength)
625 {
626 CssmData service(const_cast<void *>(reinterpret_cast<const void *>(serviceName)), serviceNameLength);
627 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
628 // use service name as default label (UNLESS the service is iTools and we have an account name [3787371])
629 const char *iTools = "iTools";
630 if (accountNameLength && serviceNameLength==strlen(iTools) && !memcmp(serviceName, iTools, serviceNameLength))
631 {
632 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
633 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), account);
634 }
635 else
636 {
637 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
638 }
639 }
640
641 if (accountName && accountNameLength)
642 {
643 CssmData account(const_cast<void *>(reinterpret_cast<const void *>(accountName)), accountNameLength);
644 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
645 }
646
647 Keychain keychain = nil;
648 try
649 {
650 keychain = Keychain::optional(keychainRef);
651 if ( !keychain->exists() )
652 {
653 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
654 }
655 }
656 catch(...)
657 {
658 keychain = globals().storageManager.defaultKeychainUI(item);
659 }
660
661 keychain->add(item);
662 if (itemRef)
663 *itemRef = item->handle();
664
665 END_SECAPI
666 }
667
668
669 OSStatus
670 SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 *passwordLength, void **passwordData, SecKeychainItemRef *itemRef)
671
672 {
673 BEGIN_SECAPI
674
675 StorageManager::KeychainList keychains;
676 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
677 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
678
679 if (serviceName && serviceNameLength)
680 {
681 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr),
682 CssmData(const_cast<char *>(serviceName), serviceNameLength));
683 }
684
685 if (accountName && accountNameLength)
686 {
687 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecAccountItemAttr),
688 CssmData(const_cast<char *>(accountName), accountNameLength));
689 }
690
691 Item item;
692 if (!cursor->next(item))
693 return errSecItemNotFound;
694
695 // Get its data (only if necessary)
696 if (passwordData || passwordLength)
697 {
698 CssmDataContainer outData;
699 item->getData(outData);
700 *passwordLength=outData.length();
701 outData.Length=0;
702 *passwordData=outData.data();
703 outData.Data=NULL;
704 }
705
706 if (itemRef)
707 *itemRef=item->handle();
708
709 END_SECAPI
710 }
711
712
713 OSStatus
714 SecKeychainSetUserInteractionAllowed(Boolean state)
715 {
716 BEGIN_SECAPI
717
718 globals().setUserInteractionAllowed(state);
719
720 END_SECAPI
721 }
722
723
724 OSStatus
725 SecKeychainGetUserInteractionAllowed(Boolean *state)
726 {
727 BEGIN_SECAPI
728
729 Required(state)=globals().getUserInteractionAllowed();
730
731 END_SECAPI
732 }
733
734
735 OSStatus
736 SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle)
737 {
738 BEGIN_SECAPI
739
740 RequiredParam(dldbHandle);
741
742 Keychain keychain = Keychain::optional(keychainRef);
743 *dldbHandle = keychain->database()->handle();
744
745 END_SECAPI
746 }
747
748
749 OSStatus
750 SecKeychainGetCSPHandle(SecKeychainRef keychainRef, CSSM_CSP_HANDLE *cspHandle)
751 {
752 BEGIN_SECAPI
753
754 RequiredParam(cspHandle);
755
756 Keychain keychain = Keychain::optional(keychainRef);
757 *cspHandle = keychain->csp()->handle();
758
759 END_SECAPI
760 }
761
762
763 OSStatus
764 SecKeychainCopyAccess(SecKeychainRef keychainRef, SecAccessRef *accessRef)
765 {
766 BEGIN_SECAPI
767
768 MacOSError::throwMe(unimpErr);//%%%for now
769
770 END_SECAPI
771 }
772
773
774 OSStatus
775 SecKeychainSetAccess(SecKeychainRef keychainRef, SecAccessRef accessRef)
776 {
777 BEGIN_SECAPI
778
779 MacOSError::throwMe(unimpErr);//%%%for now
780
781 END_SECAPI
782 }
783
784
785 #pragma mark ---- Private API ----
786
787
788 OSStatus
789 SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword)
790 {
791 BEGIN_SECAPI
792
793 Keychain keychain = Keychain::optional(keychainRef);
794 keychain->changePassphrase (oldPasswordLength, oldPassword, newPasswordLength, newPassword);
795
796 END_SECAPI
797 }
798
799
800 OSStatus
801 SecKeychainCopyLogin(SecKeychainRef *keychainRef)
802 {
803 BEGIN_SECAPI
804
805 RequiredParam(keychainRef)=globals().storageManager.loginKeychain()->handle();
806
807 END_SECAPI
808 }
809
810
811 OSStatus
812 SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password)
813 {
814 BEGIN_SECAPI
815
816 try
817 {
818 globals().storageManager.login(nameLength, name, passwordLength, password);
819 }
820 catch (CommonError &e)
821 {
822 if (e.osStatus() == CSSMERR_DL_OPERATION_AUTH_DENIED)
823 {
824 return errSecAuthFailed;
825 }
826 else
827 {
828 return e.osStatus();
829 }
830 }
831
832 END_SECAPI
833 }
834
835
836 OSStatus
837 SecKeychainLogout()
838 {
839 BEGIN_SECAPI
840
841 globals().storageManager.logout();
842
843 END_SECAPI
844 }
845
846 /* (non-exported C utility routine) 'Makes' a keychain based on a full path
847 */
848 static Keychain make(const char *name)
849 {
850 return globals().storageManager.make(name);
851 }
852
853 /* 'Makes' a keychain based on a full path for legacy "KC" CoreServices APIs.
854 Note this version doesn't take an accessRef or password.
855 The "KC" create API takes a keychainRef...
856 */
857 OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef)
858 {
859 BEGIN_SECAPI
860 RequiredParam(fullPathName);
861 RequiredParam(keychainRef)=make(fullPathName)->handle();
862 END_SECAPI
863 }
864
865
866 /* Determines if the keychainRef is a valid keychain.
867 */
868 OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
869 {
870 BEGIN_SECAPI
871 *isValid = false;
872 if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL)
873 *isValid = true;
874 END_SECAPI
875 }
876
877 /* Removes a keychain from the keychain search list for legacy "KC" CoreServices APIs.
878 */
879 OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef)
880 {
881 BEGIN_SECAPI
882 StorageManager::KeychainList singleton;
883 singleton.push_back(KeychainImpl::required(keychainRef));
884 globals().storageManager.remove(singleton);
885 END_SECAPI
886 }
887
888 /* Create a keychain based on a keychain Ref for legacy "KC" CoreServices APIs.
889 */
890 OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword)
891 {
892 BEGIN_SECAPI
893 RequiredParam(inPassword);
894 KeychainImpl::required(keychainRef)->create(passwordLength, inPassword);
895 END_SECAPI
896 }
897
898 /* Modify a keychain so that it can be synchronized.
899 */
900 OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData)
901 {
902 BEGIN_SECAPI
903
904 // do error checking for required parameters
905 RequiredParam(dbBlobArray);
906 RequiredParam(extraData);
907
908 const CssmData extraCssmData(const_cast<UInt8 *>(CFDataGetBytePtr(extraData)),
909 CFDataGetLength(extraData));
910
911 CFIndex dbBlobArrayCount = CFArrayGetCount(dbBlobArray);
912 size_t space = sizeof(uint8) + (dbBlobArrayCount * sizeof(SecurityServer::DbHandle));
913 void *dataPtr = (void*)malloc(space);
914 if ( !dataPtr )
915 return memFullErr;
916 //
917 // Get a DbHandle(IPCDbHandle) from securityd for each blob in the array that we'll authenticate with.
918 //
919 uint8* sizePtr = (uint8*)dataPtr;
920 *sizePtr = dbBlobArrayCount;
921 SecurityServer::DbHandle *currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1);
922 CFIndex index;
923 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard());
924 for (index=0; index < dbBlobArrayCount; index++)
925 {
926 CFDataRef cfBlobData = (CFDataRef)CFArrayGetValueAtIndex(dbBlobArray, index);
927 const CssmData thisKCData(const_cast<UInt8 *>(CFDataGetBytePtr(cfBlobData)), CFDataGetLength(cfBlobData));
928 //
929 // Since it's to a DbHandle that's not on our disk (it came from user's iDisk),
930 // it's OK to use the mIdentifier and access credentials of the keychain we're recoding.
931 //
932 Keychain kc = KeychainImpl::required(keychainRef);
933 *currDbHandle = ss.decodeDb(kc->dlDbIdentifier(), kc->defaultCredentials(), thisKCData); /* returns a DbHandle (IPCDbHandle) */
934
935 currDbHandle++;
936 }
937 // do the work
938 Keychain keychain = Keychain::optional(keychainRef);
939 const CssmData data(const_cast<UInt8 *>((uint8*)dataPtr), space);
940 Boolean recodeFailed = false;
941
942 int errCode=noErr;
943
944 try
945 {
946 keychain->recode(data, extraCssmData);
947 }
948 catch (MacOSError e)
949 {
950 errCode = e.osStatus();
951 recodeFailed = true;
952 }
953 catch (UnixError ue)
954 {
955 errCode = ue.unixError();
956 }
957
958 currDbHandle = (SecurityServer::DbHandle *)(sizePtr+1);
959 for (index=0; index < dbBlobArrayCount; index++)
960 {
961 ss.releaseDb(*currDbHandle);
962 currDbHandle++;
963 }
964 if ( dataPtr )
965 free(dataPtr);
966
967 if ( recodeFailed )
968 {
969 return errCode;
970 }
971
972 END_SECAPI
973 }
974
975 OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature)
976 {
977 BEGIN_SECAPI
978
979 // do error checking for required parameters
980 RequiredParam(keychainSignature);
981
982 // make a keychain object "wrapper" for this keychain ref
983 Keychain keychain = Keychain::optional(keychainRef);
984 CssmAutoData data(keychain->database()->allocator());
985 keychain->copyBlob(data.get());
986
987 // get the cssmDBBlob
988 const SecurityServer::DbBlob *cssmDBBlob =
989 data.get().interpretedAs<const SecurityServer::DbBlob>();
990
991 // convert from CDSA standards to CF standards
992 *keychainSignature = CFDataCreate(kCFAllocatorDefault,
993 cssmDBBlob->randomSignature.bytes,
994 sizeof(SecurityServer::DbBlob::Signature));
995
996 END_SECAPI
997 }
998
999 OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob)
1000 {
1001 BEGIN_SECAPI
1002
1003 // do error checking for required parameters
1004 RequiredParam(dbBlob);
1005
1006 // make a keychain object "wrapper" for this keychain ref
1007 Keychain keychain = Keychain::optional(keychainRef);
1008 CssmAutoData data(keychain->database()->allocator());
1009 keychain->copyBlob(data.get());
1010
1011 // convert from CDSA standards to CF standards
1012 *dbBlob = CFDataCreate(kCFAllocatorDefault, data, data.length());
1013
1014 END_SECAPI
1015 }
1016
1017 // make a new keychain with pre-existing secrets
1018 OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef)
1019 {
1020 BEGIN_SECAPI
1021
1022 KCThrowParamErrIf_(!fullPathName);
1023 KCThrowParamErrIf_(!dbBlob);
1024
1025 Keychain keychain = globals().storageManager.make(fullPathName);
1026
1027 CssmData blob(const_cast<unsigned char *>(CFDataGetBytePtr(dbBlob)), CFDataGetLength(dbBlob));
1028
1029 // @@@ the call to StorageManager::make above leaves keychain the the cache.
1030 // If the create below fails we should probably remove it.
1031 keychain->createWithBlob(blob);
1032
1033 RequiredParam(kcRef)=keychain->handle();
1034
1035 //
1036
1037 END_SECAPI
1038 }
1039
1040 // add a non-file based DB to the keychain list
1041 OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName,
1042 const CSSM_GUID *guid, uint32 subServiceType)
1043 {
1044 BEGIN_SECAPI
1045
1046 RequiredParam(dbName);
1047 StorageManager &smr = globals().storageManager;
1048 smr.addToDomainList(domain, dbName, *guid, subServiceType);
1049
1050 END_SECAPI
1051 }
1052
1053 // determine if a non-file based DB is in the keychain list
1054 OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName,
1055 const CSSM_GUID *guid, uint32 subServiceType)
1056 {
1057 BEGIN_SECAPI
1058 RequiredParam(dbName);
1059 StorageManager &smr = globals().storageManager;
1060 smr.isInDomainList(domain, dbName, *guid, subServiceType);
1061 END_SECAPI
1062 }
1063
1064 // remove a non-file based DB from the keychain list
1065 OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName,
1066 const CSSM_GUID *guid, uint32 subServiceType)
1067 {
1068 BEGIN_SECAPI
1069 RequiredParam(dbName);
1070 StorageManager &smr = globals().storageManager;
1071 smr.removeFromDomainList(domain, dbName, *guid, subServiceType);
1072 END_SECAPI
1073 }
1074
1075
1076 // set server mode -- must be called before any other Sec* etc. call
1077 void SecKeychainSetServerMode()
1078 {
1079 gServerMode = true;
1080 }
1081
1082
1083
1084 OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback)
1085 {
1086 BEGIN_SECAPI
1087 RequiredParam(kcRef);
1088 Keychain keychain = Keychain::optional(kcRef);
1089 keychain->setBatchMode(mode, rollback);
1090 END_SECAPI
1091 }
1092
1093
1094
1095 OSStatus SecKeychainCleanupHandles()
1096 {
1097 BEGIN_SECAPI
1098 END_SECAPI // which causes the handle cache cleanup routine to run
1099 }
1100