]>
Commit | Line | Data |
---|---|---|
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 | ||
47 | using namespace CssmClient; | |
48 | using namespace KeychainCore; | |
49 | ||
50 | StorageManager::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 | |
58 | Keychain | |
59 | StorageManager::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 | |
75 | Keychain | |
76 | StorageManager::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 | ||
105 | void | |
106 | StorageManager::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 | ||
127 | KCCursor | |
128 | StorageManager::createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList) | |
129 | { | |
130 | return KCCursor(DbCursor(mMultiDLDb), itemClass, attrList); | |
131 | } | |
132 | ||
133 | KCCursor | |
134 | StorageManager::createCursor(const SecKeychainAttributeList *attrList) | |
135 | { | |
136 | return KCCursor(DbCursor(mMultiDLDb), attrList); | |
137 | } | |
138 | ||
139 | void | |
140 | StorageManager::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 | ||
150 | void | |
151 | StorageManager::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 | ||
158 | size_t | |
159 | StorageManager::size() | |
160 | { | |
161 | reload(); | |
162 | return mMultiDLDb->list().size(); | |
163 | } | |
164 | ||
165 | Keychain | |
166 | StorageManager::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 | ||
175 | Keychain | |
176 | StorageManager::operator[](unsigned int ix) | |
177 | { | |
178 | return at(ix); | |
179 | } | |
180 | ||
181 | void 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 | ||
219 | void StorageManager::replace(const list<SecKeychainRef>& newKCList) | |
220 | { | |
221 | // replace keychains list with new list | |
222 | CssmClient::DLDbList dldbList; | |
223 | convert(newKCList,dldbList); | |
224 | } | |
225 | ||
226 | void 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 |