]> git.saurik.com Git - apple/security.git/blame - Keychain/StorageManager.cpp
Security-163.tar.gz
[apple/security.git] / Keychain / StorageManager.cpp
CommitLineData
bac41a7b 1/*
29654253 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved.
bac41a7b
A
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19/*
20 File: StorageManager.cpp
21
22 Contains: Working with multiple keychains
23
bac41a7b
A
24*/
25
26#include "StorageManager.h"
27#include "KCEventNotifier.h"
28
29#include <Security/cssmapple.h>
30#include <sys/types.h>
df0e469f
A
31#include <sys/param.h>
32#include <syslog.h>
bac41a7b
A
33#include <pwd.h>
34#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
35#include <algorithm>
36#include <string>
bac41a7b
A
37#include <Security/AuthorizationTags.h>
38#include <Security/AuthSession.h>
39#include <Security/debugging.h>
29654253 40#include <Security/SecCFTypes.h>
df0e469f
A
41#include <Security/AuthSession.h>
42#include <Security/SecurityAgentClient.h>
43#include <Security/ssclient.h>
bac41a7b
A
44
45#include "KCCursor.h"
46#include "Globals.h"
bac41a7b
A
47
48using namespace CssmClient;
49using namespace KeychainCore;
50
df0e469f
A
51// normal debug calls, which get stubbed out for deployment builds
52#define x_debug(str) secdebug("KClogin",(str))
53#define x_debug1(fmt,arg1) secdebug("KClogin",(fmt),(arg1))
54#define x_debug2(fmt,arg1,arg2) secdebug("KClogin",(fmt),(arg1),(arg2))
55
56//-----------------------------------------------------------------------------------
57
bac41a7b 58StorageManager::StorageManager() :
df0e469f
A
59 mSavedList(kSecPreferencesDomainUser),
60 mCommonList(kSecPreferencesDomainCommon),
61 mDomain(kSecPreferencesDomainUser),
62 mKeychains()
bac41a7b 63{
df0e469f
A
64 // get session attributes
65 SessionAttributeBits sessionAttrs;
66 if (OSStatus err = SessionGetInfo(callerSecuritySession,
67 NULL, &sessionAttrs))
68 CssmError::throwMe(err);
69
70 // If this is the root session, switch to system preferences.
71 // (In SecurityServer debug mode, you'll get a (fake) root session
72 // that has graphics access. Ignore that to help testing.)
73 if ((sessionAttrs & sessionIsRoot)
74 IFDEBUG( && !(sessionAttrs & sessionHasGraphicAccess))) {
75 secdebug("storagemgr", "switching to system preferences");
76 mDomain = kSecPreferencesDomainSystem;
77 mSavedList.set(kSecPreferencesDomainSystem);
78 }
bac41a7b
A
79}
80
81// Create KC if it doesn't exist
82Keychain
83StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier)
84{
29654253
A
85 StLock<Mutex> _(mLock);
86 return _keychain(dLDbIdentifier);
87}
88
89Keychain
90StorageManager::_keychain(const DLDbIdentifier &dLDbIdentifier)
91{
df0e469f
A
92 if (!dLDbIdentifier)
93 return Keychain();
94
bac41a7b
A
95 KeychainMap::iterator it = mKeychains.find(dLDbIdentifier);
96 if (it != mKeychains.end())
97 return it->second;
98
99 // The keychain is not in our cache. Create it.
29654253
A
100 Module module(dLDbIdentifier.ssuid().guid());
101 DL dl;
102 if (dLDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP)
103 dl = SSCSPDL(module);
104 else
105 dl = DL(module);
106
107 dl->subserviceId(dLDbIdentifier.ssuid().subserviceId());
108 dl->version(dLDbIdentifier.ssuid().version());
109 Db db(dl, dLDbIdentifier.dbName());
bac41a7b 110
df0e469f 111 Keychain keychain(db);
bac41a7b 112 // Add the keychain to the cache.
df0e469f
A
113 mKeychains.insert(KeychainMap::value_type(dLDbIdentifier, &*keychain));
114
bac41a7b
A
115 return keychain;
116}
117
df0e469f
A
118// Called from KeychainImpl's destructor remove it from the map.
119void
120StorageManager::removeKeychain(const DLDbIdentifier &dLDbIdentifier, KeychainImpl *keychainImpl)
121{
122 // @@@ Work out locking StLock<Mutex> _(mLock);
123 KeychainMap::iterator it = mKeychains.find(dLDbIdentifier);
124 if (it != mKeychains.end() && it->second == keychainImpl)
125 mKeychains.erase(it);
126}
127
128// if a database is key-unlockable, authenticate it with any matching unlock keys found in the KC list
129void StorageManager::setDefaultCredentials(const Db &db)
130{
131 try {
132 CssmAutoData index(db->allocator());
133 if (!db->getUnlockKeyIndex(index.get()))
134 return; // no suggested index (probably not a CSPDL)
135
136 TrackingAllocator alloc(CssmAllocator::standard());
137
138 KCCursor search(createCursor(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, NULL));
139 CssmAutoData keyLabel(CssmAllocator::standard());
140 keyLabel = StringData("SYSKC**");
141 keyLabel.append(index);
142 static const CSSM_DB_ATTRIBUTE_INFO infoLabel = {
143 CSSM_DB_ATTRIBUTE_NAME_AS_STRING,
144 {"Label"},
145 CSSM_DB_ATTRIBUTE_FORMAT_BLOB
146 };
147 search->add(CSSM_DB_EQUAL, infoLabel, keyLabel.get());
148
149 // could run a loop below to catch *all* eligible keys,
150 // but that's stretching it; and beware CSP scope if you add this...
151 AutoCredentials cred(alloc);
152 Item keyItem;
153 if (search->next(keyItem)) {
154 CssmClient::Key key = dynamic_cast<KeyItem &>(*keyItem).key();
155
156 // create AccessCredentials from that key. Still allow interactive unlock
157 const CssmKey &masterKey = key;
158 CSSM_CSP_HANDLE cspHandle = key->csp()->handle();
159 cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
160 new(alloc) ListElement(CSSM_WORDID_SYMMETRIC_KEY),
161 new(alloc) ListElement(CssmData::wrap(cspHandle)),
162 new(alloc) ListElement(CssmData::wrap(masterKey)));
163 cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
164 new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT));
165
166 secdebug("storagemgr", "authenticating %s for default key credentials", db->name());
167 db->authenticate(db->accessRequest(), &cred);
168 }
169 } catch (...) {
170 secdebug("storagemgr", "setDefaultCredentials for %s abandoned due to exception", db->name());
171 }
172}
173
29654253 174// Create KC if it doesn't exist, add it to the search list if it exists and is not already on it.
bac41a7b 175Keychain
df0e469f 176StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add)
bac41a7b 177{
df0e469f
A
178 Keychain keychain;
179 bool post = false;
bac41a7b 180
bac41a7b 181 {
29654253 182 StLock<Mutex> _(mLock);
df0e469f
A
183 keychain = _keychain(dLDbIdentifier);
184
185 if (add)
29654253 186 {
df0e469f
A
187 mSavedList.revert(false);
188 DLDbList searchList = mSavedList.searchList();
189 if (find(searchList.begin(), searchList.end(), dLDbIdentifier) != searchList.end())
190 return keychain; // Keychain is already in the searchList.
191
192 mCommonList.revert(false);
193 searchList = mCommonList.searchList();
194 if (find(searchList.begin(), searchList.end(), dLDbIdentifier) != searchList.end())
195 return keychain; // Keychain is already in the commonList don't add it to the searchList.
196
197 // If the keychain doesn't exist don't bother adding it to the search list yet.
198 if (!keychain->exists())
199 return keychain;
200
201 // The keychain exists and is not in our search list add it to the search
202 // list and the cache.
203 mSavedList.revert(true);
204 mSavedList.add(dLDbIdentifier);
205 mSavedList.save();
206 post = true;
29654253 207 }
bac41a7b
A
208 }
209
df0e469f
A
210 if (post)
211 {
212 // Make sure we are not holding mLock when we post this event.
213 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
214 }
bac41a7b
A
215
216 return keychain;
217}
218
219void
220StorageManager::created(const Keychain &keychain) // Be notified a Keychain just got created.
221{
222 DLDbIdentifier dLDbIdentifier = keychain->dLDbIdentifier();
df0e469f 223 bool defaultChanged = false;
bac41a7b 224
29654253
A
225 {
226 StLock<Mutex> _(mLock);
bac41a7b 227
29654253 228 mSavedList.revert(true);
df0e469f
A
229 // If we don't have a default Keychain yet. Make the newly created keychain the default.
230 if (!mSavedList.defaultDLDbIdentifier())
231 {
232 mSavedList.defaultDLDbIdentifier(dLDbIdentifier);
233 defaultChanged = true;
234 }
235
236 // Add the keychain to the search list prefs.
29654253
A
237 mSavedList.add(dLDbIdentifier);
238 mSavedList.save();
29654253 239 }
bac41a7b 240
df0e469f 241 // Make sure we are not holding mLock when we post these events.
bac41a7b 242 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
df0e469f
A
243
244 if (defaultChanged)
245 {
246 KCEventNotifier::PostKeychainEvent(kSecDefaultChangedEvent, dLDbIdentifier);
247 }
bac41a7b
A
248}
249
bac41a7b
A
250KCCursor
251StorageManager::createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList)
252{
df0e469f
A
253 KeychainList searchList;
254 getSearchList(searchList);
255 return KCCursor(searchList, itemClass, attrList);
bac41a7b
A
256}
257
258KCCursor
259StorageManager::createCursor(const SecKeychainAttributeList *attrList)
260{
df0e469f
A
261 KeychainList searchList;
262 getSearchList(searchList);
263 return KCCursor(searchList, attrList);
bac41a7b
A
264}
265
266void
267StorageManager::lockAll()
268{
df0e469f
A
269 SecurityServer::ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard());
270 ss.lockAll (false);
271}
272
273Keychain
274StorageManager::defaultKeychain()
275{
276 Keychain theKeychain;
277 {
278 StLock<Mutex> _(mLock);
279 mSavedList.revert(false);
280 DLDbIdentifier defaultDLDbIdentifier(mSavedList.defaultDLDbIdentifier());
281 if (defaultDLDbIdentifier)
282 {
283 theKeychain = _keychain(defaultDLDbIdentifier);
284 }
285 }
286
287 if (theKeychain /* && theKeychain->exists() */)
288 return theKeychain;
289
290 MacOSError::throwMe(errSecNoDefaultKeychain);
291}
292
293void
294StorageManager::defaultKeychain(const Keychain &keychain)
295{
296 DLDbIdentifier oldDefaultId;
297 DLDbIdentifier newDefaultId(keychain->dLDbIdentifier());
bac41a7b 298 {
29654253 299 StLock<Mutex> _(mLock);
df0e469f
A
300 oldDefaultId = mSavedList.defaultDLDbIdentifier();
301 mSavedList.revert(true);
302 mSavedList.defaultDLDbIdentifier(newDefaultId);
303 mSavedList.save();
29654253
A
304 }
305
df0e469f 306 if (!(oldDefaultId == newDefaultId))
29654253 307 {
df0e469f
A
308 // Make sure we are not holding mLock when we post this event.
309 KCEventNotifier::PostKeychainEvent(kSecDefaultChangedEvent, newDefaultId);
bac41a7b
A
310 }
311}
312
df0e469f
A
313Keychain
314StorageManager::defaultKeychain(SecPreferencesDomain domain)
29654253 315{
df0e469f
A
316 if (domain == mDomain)
317 return defaultKeychain();
318 else
29654253 319 {
df0e469f
A
320 DLDbIdentifier defaultDLDbIdentifier(DLDbListCFPref(domain).defaultDLDbIdentifier());
321 if (defaultDLDbIdentifier)
322 return keychain(defaultDLDbIdentifier);
323
324 MacOSError::throwMe(errSecNoDefaultKeychain);
29654253 325 }
29654253
A
326}
327
bac41a7b 328void
df0e469f 329StorageManager::defaultKeychain(SecPreferencesDomain domain, const Keychain &keychain)
29654253 330{
df0e469f
A
331 if (domain == mDomain)
332 defaultKeychain(keychain);
333 else
334 DLDbListCFPref(domain).defaultDLDbIdentifier(keychain->dLDbIdentifier());
335}
336
337Keychain
338StorageManager::loginKeychain()
339{
340 Keychain theKeychain;
341 {
342 StLock<Mutex> _(mLock);
343 mSavedList.revert(false);
344 DLDbIdentifier loginDLDbIdentifier(mSavedList.loginDLDbIdentifier());
345 if (loginDLDbIdentifier)
346 {
347 theKeychain = _keychain(loginDLDbIdentifier);
348 }
349 }
350
351 if (theKeychain && theKeychain->exists())
352 return theKeychain;
353
354 MacOSError::throwMe(errSecNoSuchKeychain);
29654253
A
355}
356
357void
df0e469f 358StorageManager::loginKeychain(Keychain keychain)
bac41a7b 359{
df0e469f
A
360 StLock<Mutex> _(mLock);
361 mSavedList.revert(true);
362 mSavedList.loginDLDbIdentifier(keychain->dLDbIdentifier());
363 mSavedList.save();
bac41a7b
A
364}
365
366size_t
367StorageManager::size()
368{
29654253 369 StLock<Mutex> _(mLock);
df0e469f
A
370 mSavedList.revert(false);
371 mCommonList.revert(false);
372 return mSavedList.searchList().size() + mCommonList.searchList().size();
bac41a7b
A
373}
374
375Keychain
376StorageManager::at(unsigned int ix)
377{
29654253 378 StLock<Mutex> _(mLock);
df0e469f
A
379 mSavedList.revert(false);
380 DLDbList dLDbList = mSavedList.searchList();
381 if (ix < dLDbList.size())
382 {
383 return _keychain(dLDbList[ix]);
384 }
385 else
386 {
387 ix -= dLDbList.size();
388 mCommonList.revert(false);
389 DLDbList commonList = mCommonList.searchList();
390 if (ix >= commonList.size())
391 MacOSError::throwMe(errSecInvalidKeychain);
bac41a7b 392
df0e469f
A
393 return _keychain(commonList[ix]);
394 }
bac41a7b
A
395}
396
397Keychain
398StorageManager::operator[](unsigned int ix)
399{
400 return at(ix);
401}
402
df0e469f
A
403void StorageManager::rename(Keychain keychain, const char* newName)
404{
405 // This is not a generic purpose rename method for keychains.
406 // The keychain doesn't remain in the cache.
407 //
408 bool changedDefault = false;
409 DLDbIdentifier newDLDbIdentifier;
410 {
411 StLock<Mutex> _(mLock);
412 mSavedList.revert(true);
413 DLDbIdentifier defaultId = mSavedList.defaultDLDbIdentifier();
414
415 // Find the keychain object for the given ref
416 DLDbIdentifier dLDbIdentifier = keychain->dLDbIdentifier();
417
418 // Remove it from the saved list
419 mSavedList.remove(dLDbIdentifier);
420 if (dLDbIdentifier == defaultId)
421 changedDefault=true;
422
423 // Actually rename the database on disk.
424 keychain->database()->rename(newName);
425
426 newDLDbIdentifier = keychain->dLDbIdentifier();
427
428 // Now update the keychain map to use the newDLDbIdentifier
429 KeychainMap::iterator it = mKeychains.find(dLDbIdentifier);
430 if (it != mKeychains.end())
431 {
432 mKeychains.erase(it);
433 mKeychains.insert(KeychainMap::value_type(newDLDbIdentifier, keychain));
434 }
435
436 // If this was the default keychain change it accordingly
437 if (changedDefault)
438 mSavedList.defaultDLDbIdentifier(newDLDbIdentifier);
439
440 mSavedList.save();
441 }
442
443 // @@@ We need a kSecKeychainRenamedEvent so other clients can close this keychain and move on with life.
444 //KCEventNotifier::PostKeychainEvent(kSecKeychainRenamedEvent);
445
446 // Make sure we are not holding mLock when we post these events.
447 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
448
449 if (changedDefault)
450 KCEventNotifier::PostKeychainEvent(kSecDefaultChangedEvent, newDLDbIdentifier);
451}
452
453void StorageManager::renameUnique(Keychain keychain, CFStringRef newName)
454{
455 bool doneCreating = false;
456 int index = 1;
457 do
458 {
459 char newNameCString[MAXPATHLEN];
460 if ( CFStringGetCString(newName, newNameCString, MAXPATHLEN, kCFStringEncodingUTF8) ) // make sure it fits in MAXPATHLEN, etc.
461 {
462 // Construct the new name...
463 //
464 CFMutableStringRef newNameCFStr = NULL;
465 newNameCFStr = CFStringCreateMutable(NULL, MAXPATHLEN);
466 if ( newNameCFStr )
467 {
468 CFStringAppendFormat(newNameCFStr, NULL, CFSTR("%s%d"), &newNameCString, index);
469 CFStringAppend(newNameCFStr, CFSTR(kKeychainSuffix)); // add .keychain
470 char toUseBuff2[MAXPATHLEN];
471 if ( CFStringGetCString(newNameCFStr, toUseBuff2, MAXPATHLEN, kCFStringEncodingUTF8) ) // make sure it fits in MAXPATHLEN, etc.
472 {
473 struct stat filebuf;
474 if ( lstat(toUseBuff2, &filebuf) )
475 {
476 rename(keychain, toUseBuff2);
477 doneCreating = true;
478 }
479 else
480 index++;
481 }
482 else
483 doneCreating = true; // failure to get c string.
484 CFRelease(newNameCFStr);
485 }
486 else
487 doneCreating = false; // failure to create mutable string.
488 }
489 else
490 doneCreating = false; // failure to get the string (i.e. > MAXPATHLEN?)
491 }
492 while (!doneCreating && index != INT_MAX);
493}
494
29654253 495void StorageManager::remove(const KeychainList &kcsToRemove, bool deleteDb)
bac41a7b 496{
29654253 497 bool unsetDefault = false;
bac41a7b 498 {
29654253
A
499 StLock<Mutex> _(mLock);
500 mSavedList.revert(true);
df0e469f 501 DLDbIdentifier defaultId = mSavedList.defaultDLDbIdentifier();
29654253 502 for (KeychainList::const_iterator ix = kcsToRemove.begin(); ix != kcsToRemove.end(); ++ix)
bac41a7b 503 {
29654253
A
504 // Find the keychain object for the given ref
505 Keychain keychainToRemove = *ix;
506 DLDbIdentifier dLDbIdentifier = keychainToRemove->dLDbIdentifier();
507
508 // Remove it from the saved list
509 mSavedList.remove(dLDbIdentifier);
510 if (dLDbIdentifier == defaultId)
511 unsetDefault=true;
512
513 if (deleteDb)
514 {
515 keychainToRemove->database()->deleteDb();
516 // Now remove it from the map
517 KeychainMap::iterator it = mKeychains.find(dLDbIdentifier);
518 if (it == mKeychains.end())
519 continue;
520 mKeychains.erase(it);
521 }
bac41a7b 522 }
df0e469f
A
523
524 if (unsetDefault)
525 mSavedList.defaultDLDbIdentifier(DLDbIdentifier());
526
29654253 527 mSavedList.save();
bac41a7b 528 }
29654253 529
df0e469f 530 // Make sure we are not holding mLock when we post these events.
bac41a7b 531 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
29654253 532
bac41a7b 533 if (unsetDefault)
df0e469f 534 KCEventNotifier::PostKeychainEvent(kSecDefaultChangedEvent);
29654253
A
535}
536
537void
538StorageManager::getSearchList(KeychainList &keychainList)
539{
29654253 540 StLock<Mutex> _(mLock);
df0e469f
A
541 mSavedList.revert(false);
542 mCommonList.revert(false);
543
544 // Merge mSavedList and common list
545 DLDbList dLDbList = mSavedList.searchList();
546 DLDbList commonList = mCommonList.searchList();
547 KeychainList result;
548 result.reserve(dLDbList.size() + commonList.size());
549
550 for (DLDbList::const_iterator it = dLDbList.begin(); it != dLDbList.end(); ++it)
551 {
552 Keychain keychain(_keychain(*it));
553 result.push_back(keychain);
554 }
555
556 for (DLDbList::const_iterator it = commonList.begin(); it != commonList.end(); ++it)
557 {
558 Keychain keychain(_keychain(*it));
559 result.push_back(keychain);
560 }
29654253 561
df0e469f 562 keychainList.swap(result);
bac41a7b
A
563}
564
29654253
A
565void
566StorageManager::setSearchList(const KeychainList &keychainList)
bac41a7b 567{
df0e469f
A
568 DLDbList commonList = mCommonList.searchList();
569
570 // Strip out the common list part from the end of the search list.
571 KeychainList::const_iterator it_end = keychainList.end();
572 DLDbList::const_reverse_iterator end_common = commonList.rend();
573 for (DLDbList::const_reverse_iterator it_common = commonList.rbegin(); it_common != end_common; ++it_common)
574 {
575 // Eliminate common entries from the end of the passed in keychainList.
576 if (it_end == keychainList.begin())
577 break;
578
579 --it_end;
580 if (!((*it_end)->dLDbIdentifier() == *it_common))
581 {
582 ++it_end;
583 break;
584 }
585 }
586
587 /* it_end now points one past the last element in keychainList which is not in commonList. */
588 DLDbList searchList, oldSearchList(mSavedList.searchList());
589 for (KeychainList::const_iterator it = keychainList.begin(); it != it_end; ++it)
590 {
591 searchList.push_back((*it)->dLDbIdentifier());
592 }
593
594 {
595 // Set the current searchlist to be what was passed in, the old list will be freed
596 // upon exit of this stackframe.
597 StLock<Mutex> _(mLock);
598 mSavedList.revert(true);
599 mSavedList.searchList(searchList);
600 mSavedList.save();
601 }
29654253 602
df0e469f
A
603 if (!(oldSearchList == searchList))
604 {
605 // Make sure we are not holding mLock when we post this event.
606 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
607 }
608}
609
610void
611StorageManager::getSearchList(SecPreferencesDomain domain, KeychainList &keychainList)
612{
613 if (domain == mDomain)
614 {
615 StLock<Mutex> _(mLock);
616 mSavedList.revert(false);
617 convertList(keychainList, mSavedList.searchList());
618 }
619 else
620 {
621 convertList(keychainList, DLDbListCFPref(domain).searchList());
622 }
623}
624
625void
626StorageManager::setSearchList(SecPreferencesDomain domain, const KeychainList &keychainList)
627{
628 DLDbList searchList;
629 convertList(searchList, keychainList);
630
631 if (domain == mDomain)
632 {
633 DLDbList oldSearchList(mSavedList.searchList());
634 {
635 // Set the current searchlist to be what was passed in, the old list will be freed
636 // upon exit of this stackframe.
637 StLock<Mutex> _(mLock);
638 mSavedList.revert(true);
639 mSavedList.searchList(searchList);
640 mSavedList.save();
641 }
642
643 if (!(oldSearchList == searchList))
644 {
645 // Make sure we are not holding mLock when we post this event.
646 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
647 }
648 }
649 else
650 {
651 DLDbListCFPref(domain).searchList(searchList);
652 }
653}
654
655void
656StorageManager::domain(SecPreferencesDomain domain)
657{
29654253 658 StLock<Mutex> _(mLock);
df0e469f
A
659 if (domain == mDomain)
660 return; // no change
661
662#if !defined(NDEBUG)
663 switch (domain)
664 {
665 case kSecPreferencesDomainSystem:
666 secdebug("storagemgr", "switching to system domain"); break;
667 case kSecPreferencesDomainUser:
668 secdebug("storagemgr", "switching to user domain (uid %d)", getuid()); break;
669 default:
670 secdebug("storagemgr", "switching to weird prefs domain %d", domain); break;
671 }
672#endif
673
674 mDomain = domain;
675 mSavedList.set(domain);
bac41a7b
A
676}
677
29654253
A
678void
679StorageManager::optionalSearchList(CFTypeRef keychainOrArray, KeychainList &keychainList)
bac41a7b 680{
29654253
A
681 if (!keychainOrArray)
682 getSearchList(keychainList);
683 else
bac41a7b 684 {
29654253
A
685 CFTypeID typeID = CFGetTypeID(keychainOrArray);
686 if (typeID == CFArrayGetTypeID())
687 convertToKeychainList(CFArrayRef(keychainOrArray), keychainList);
df0e469f
A
688 else if (typeID == gTypes().KeychainImpl.typeID)
689 keychainList.push_back(KeychainImpl::required(SecKeychainRef(keychainOrArray)));
29654253
A
690 else
691 MacOSError::throwMe(paramErr);
692 }
693}
694
695// static methods.
696void
697StorageManager::convertToKeychainList(CFArrayRef keychainArray, KeychainList &keychainList)
698{
699 assert(keychainArray);
700 CFIndex count = CFArrayGetCount(keychainArray);
701 KeychainList keychains(count);
29654253
A
702 for (CFIndex ix = 0; ix < count; ++ix)
703 {
df0e469f 704 keychains[ix] = KeychainImpl::required(SecKeychainRef(CFArrayGetValueAtIndex(keychainArray, ix)));
29654253
A
705 }
706
707 keychainList.swap(keychains);
708}
709
710CFArrayRef
711StorageManager::convertFromKeychainList(const KeychainList &keychainList)
712{
713 CFRef<CFMutableArrayRef> keychainArray(CFArrayCreateMutable(NULL, keychainList.size(), &kCFTypeArrayCallBacks));
714
29654253
A
715 for (KeychainList::const_iterator ix = keychainList.begin(); ix != keychainList.end(); ++ix)
716 {
df0e469f 717 SecKeychainRef keychainRef = (*ix)->handle();
29654253
A
718 CFArrayAppendValue(keychainArray, keychainRef);
719 CFRelease(keychainRef);
bac41a7b 720 }
29654253
A
721
722 // Counter the CFRelease that CFRef<> is about to do when keychainArray goes out of scope.
723 CFRetain(keychainArray);
724 return keychainArray;
bac41a7b
A
725}
726
df0e469f
A
727void StorageManager::convertList(DLDbList &ids, const KeychainList &kcs)
728{
729 DLDbList result;
730 result.reserve(kcs.size());
731 for (KeychainList::const_iterator ix = kcs.begin(); ix != kcs.end(); ++ix)
732 {
733 result.push_back((*ix)->dLDbIdentifier());
734 }
735 ids.swap(result);
736}
bac41a7b 737
df0e469f
A
738void StorageManager::convertList(KeychainList &kcs, const DLDbList &ids)
739{
740 KeychainList result;
741 result.reserve(ids.size());
742 for (DLDbList::const_iterator ix = ids.begin(); ix != ids.end(); ++ix)
743 {
744 Keychain keychain(_keychain(*ix));
745 result.push_back(keychain);
746 }
747 kcs.swap(result);
748}
29654253 749
bac41a7b
A
750