]> git.saurik.com Git - apple/security.git/blame - Keychain/StorageManager.cpp
Security-30.1.tar.gz
[apple/security.git] / Keychain / StorageManager.cpp
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
24 Copyright: 2000 by Apple Computer, Inc., all rights reserved.
25
26 To Do:
27*/
28
29#include "StorageManager.h"
30#include "KCEventNotifier.h"
31
32#include <Security/cssmapple.h>
33#include <sys/types.h>
34#include <pwd.h>
35#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
36#include <algorithm>
37#include <string>
38#include <Security/Authorization.h>
39#include <Security/AuthorizationTags.h>
40#include <Security/AuthSession.h>
41#include <Security/debugging.h>
42
43#include "KCCursor.h"
44#include "Globals.h"
45#include "DefaultKeychain.h"
46
47using namespace CssmClient;
48using namespace KeychainCore;
49
50StorageManager::StorageManager() :
51 mSavedList(),
52 mKeychains(),
53 mMultiDLDb(mSavedList.list(), true) // Passinng true enables use of Secure Storage
54{
55}
56
57// Create KC if it doesn't exist
58Keychain
59StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier)
60{
61 //StLock<Mutex> _(mKeychainsLock);
62 KeychainMap::iterator it = mKeychains.find(dLDbIdentifier);
63 if (it != mKeychains.end())
64 return it->second;
65
66 // The keychain is not in our cache. Create it.
67 Keychain keychain(mMultiDLDb->database(dLDbIdentifier));
68
69 // Add the keychain to the cache.
70 mKeychains.insert(KeychainMap::value_type(dLDbIdentifier, keychain));
71 return keychain;
72}
73
74// Create KC if it doesn't exist
75Keychain
76StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier)
77{
78 Keychain keychain(keychain(dLDbIdentifier));
79
80 const vector<DLDbIdentifier> &list = mMultiDLDb->list();
81 if (find(list.begin(), list.end(), dLDbIdentifier) != list.end())
82 {
83 // The dLDbIdentifier for this keychain is already on our search list.
84 return keychain;
85 }
86
87 // If the keychain doesn't exist don't bother adding it to the search list yet.
88 if (!keychain->exists())
89 return keychain;
90
91 // The keychain exists and is not in our search list add it to the search
92 // list and the cache. Then inform mMultiDLDb.
93 mSavedList.revert(true);
94 mSavedList.add(dLDbIdentifier);
95 mSavedList.save();
96
97 // @@@ Will happen again when kSecKeychainListChangedEvent notification is received.
98 mMultiDLDb->list(mSavedList.list());
99
100 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
101
102 return keychain;
103}
104
105void
106StorageManager::created(const Keychain &keychain) // Be notified a Keychain just got created.
107{
108 DLDbIdentifier dLDbIdentifier = keychain->dLDbIdentifier();
109
110 // If we don't have a default Keychain yet. Make the newly created keychain the default.
111 DefaultKeychain &defaultKeychain = globals().defaultKeychain;
112 if (!defaultKeychain.isSet())
113 defaultKeychain.dLDbIdentifier(dLDbIdentifier);
114
115 // Add the keychain to the search list and the cache. Then inform mMultiDLDb.
116 mSavedList.revert(true);
117 mSavedList.add(dLDbIdentifier);
118 mSavedList.save();
119
120 // @@@ Will happen again when kSecKeychainListChangedEvent notification is received.
121 mMultiDLDb->list(mSavedList.list());
122
123 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
124}
125
126
127KCCursor
128StorageManager::createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList)
129{
130 return KCCursor(DbCursor(mMultiDLDb), itemClass, attrList);
131}
132
133KCCursor
134StorageManager::createCursor(const SecKeychainAttributeList *attrList)
135{
136 return KCCursor(DbCursor(mMultiDLDb), attrList);
137}
138
139void
140StorageManager::lockAll()
141{
142 for (KeychainMap::iterator ix = mKeychains.begin(); ix != mKeychains.end(); ix++)
143 {
144 Keychain keychain(ix->second);
145 if (keychain->isActive())
146 keychain->lock();
147 }
148}
149
150void
151StorageManager::reload(bool force)
152{
153 // Reinitialize list from CFPrefs if changed. When force is true force a prefs revert now.
154 if (mSavedList.revert(force))
155 mMultiDLDb->list(mSavedList.list());
156}
157
158size_t
159StorageManager::size()
160{
161 reload();
162 return mMultiDLDb->list().size();
163}
164
165Keychain
166StorageManager::at(unsigned int ix)
167{
168 reload();
169 if (ix >= mMultiDLDb->list().size())
170 MacOSError::throwMe(errSecInvalidKeychain);
171
172 return keychain(mMultiDLDb->list().at(ix));
173}
174
175Keychain
176StorageManager::operator[](unsigned int ix)
177{
178 return at(ix);
179}
180
181void StorageManager::remove(const list<SecKeychainRef>& kcsToRemove)
182{
183 //StLock<Mutex> _(mKeychainsLock);
184 mSavedList.revert(true);
185 DLDbIdentifier defaultId = globals().defaultKeychain.dLDbIdentifier();
186 bool unsetDefault=false;
187 for (list<SecKeychainRef>::const_iterator ix = kcsToRemove.begin();ix!=kcsToRemove.end();ix++)
188 {
189 // Find the keychain object for the given ref
190 Keychain keychainToRemove;
191 try
192 {
193 keychainToRemove = KeychainRef::required(*ix);
194 }
195 catch (const MacOSError& err)
196 {
197 if (err.osStatus() == errSecInvalidKeychain)
198 continue;
199 throw;
200 }
201
202 // Remove it from the saved list
203 mSavedList.remove(keychainToRemove->dLDbIdentifier());
204 if (keychainToRemove->dLDbIdentifier() == defaultId)
205 unsetDefault=true;
206 // Now remove it from the map
207 KeychainMap::iterator it = mKeychains.find(keychainToRemove->dLDbIdentifier());
208 if (it==mKeychains.end())
209 continue;
210 mKeychains.erase(it);
211 }
212 mSavedList.save();
213 mMultiDLDb->list(mSavedList.list());
214 KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
215 if (unsetDefault)
216 globals().defaultKeychain.unset();
217}
218
219void StorageManager::replace(const list<SecKeychainRef>& newKCList)
220{
221 // replace keychains list with new list
222 CssmClient::DLDbList dldbList;
223 convert(newKCList,dldbList);
224}
225
226void StorageManager::convert(const list<SecKeychainRef>& SecKeychainRefList,CssmClient::DLDbList& dldbList)
227{
228 // Convert a list of SecKeychainRefs to a DLDbList
229 dldbList.clear(); // If we don't clear list, we should use "add" instead of push_back
230 for (list<SecKeychainRef>::const_iterator ix = SecKeychainRefList.begin();ix!=SecKeychainRefList.end();ix++)
231 {
232 // Find the keychain object for the given ref
233 Keychain keychain;
234 try
235 {
236 keychain = KeychainRef::required(*ix);
237 }
238 catch (const MacOSError& err)
239 {
240 if (err.osStatus() == errSecInvalidKeychain)
241 continue;
242 throw;
243 }
244
245 // Add it to the list
246 dldbList.push_back(keychain->dLDbIdentifier());
247 }
248}
249
250
251