]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/Keychains.h
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / Keychains.h
1 /*
2 * Copyright (c) 2000-2004,2011-2014 Apple 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 //
25 // Keychains.h - The Keychain class
26 //
27 #ifndef _SECURITY_KEYCHAINS_H_
28 #define _SECURITY_KEYCHAINS_H_
29
30 #include <security_cdsa_client/cspclient.h>
31 #include <security_cdsa_client/dlclient.h>
32 #include <security_utilities/refcount.h>
33 #include <security_utilities/seccfobject.h>
34 #include <Security/SecKeychain.h>
35 #include <Security/SecKeychainItem.h>
36 #include <memory>
37 #include "SecCFTypes.h"
38 #include "defaultcreds.h"
39
40 class EventBuffer;
41
42 namespace Security
43 {
44
45 namespace KeychainCore
46 {
47
48 class KCCursor;
49 class Item;
50 class PrimaryKey;
51 class StorageManager;
52
53 class KeychainSchemaImpl : public RefCount
54 {
55 NOCOPY(KeychainSchemaImpl)
56 public:
57 friend class KeychainSchema;
58 protected:
59 KeychainSchemaImpl(const CssmClient::Db &db);
60 public:
61 virtual ~KeychainSchemaImpl();
62
63 CSSM_DB_ATTRIBUTE_FORMAT attributeFormatFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const;
64 const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) const;
65
66 bool operator <(const KeychainSchemaImpl &other) const;
67 bool operator ==(const KeychainSchemaImpl &other) const;
68
69 void getAttributeInfoForRecordType(CSSM_DB_RECORDTYPE recordType, SecKeychainAttributeInfo **Info) const;
70 CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const;
71 bool hasAttribute(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const;
72 bool hasRecordType(CSSM_DB_RECORDTYPE recordType) const;
73
74 void didCreateRelation(CSSM_DB_RECORDTYPE inRelationID,
75 const char *inRelationName,
76 uint32 inNumberOfAttributes,
77 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo,
78 uint32 inNumberOfIndexes,
79 const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo);
80
81 private:
82 typedef map<CSSM_DB_RECORDTYPE, CssmAutoDbRecordAttributeInfo *> PrimaryKeyInfoMap;
83 PrimaryKeyInfoMap mPrimaryKeyInfoMap;
84
85 typedef map<uint32, CSSM_DB_ATTRIBUTE_FORMAT> RelationInfoMap;
86 typedef map<CSSM_DB_RECORDTYPE, RelationInfoMap> DatabaseInfoMap;
87 DatabaseInfoMap mDatabaseInfoMap;
88 Mutex mMutex;
89
90 private:
91 const RelationInfoMap &relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const;
92 };
93
94
95 class KeychainSchema : public RefPointer<KeychainSchemaImpl>
96 {
97 public:
98 KeychainSchema() {}
99 KeychainSchema(KeychainSchemaImpl *impl) : RefPointer<KeychainSchemaImpl>(impl) {}
100 KeychainSchema(const CssmClient::Db &db) : RefPointer<KeychainSchemaImpl>(new KeychainSchemaImpl(db)) {}
101 ~KeychainSchema();
102
103 bool operator <(const KeychainSchema &other) const
104 { return ptr && other.ptr ? *ptr < *other.ptr : ptr < other.ptr; }
105 bool operator ==(const KeychainSchema &other) const
106 { return ptr && other.ptr ? *ptr == *other.ptr : ptr == other.ptr; }
107
108 private:
109 typedef KeychainSchemaImpl Impl;
110 };
111
112
113 class ItemImpl;
114
115 class KeychainImpl : public SecCFObject, private CssmClient::Db::DefaultCredentialsMaker
116 {
117 NOCOPY(KeychainImpl)
118 public:
119 SECCFFUNCTIONS(KeychainImpl, SecKeychainRef, errSecInvalidKeychain, gTypes().KeychainImpl)
120
121 friend class Keychain;
122 friend class ItemImpl;
123 friend class KeyItem;
124 friend class KCCursorImpl;
125 friend class StorageManager;
126 protected:
127 KeychainImpl(const CssmClient::Db &db);
128
129 protected:
130 // Methods called by ItemImpl;
131 void didUpdate(const Item &inItem, PrimaryKey &oldPK,
132 PrimaryKey &newPK);
133 void completeAdd(Item &item, PrimaryKey &key);
134
135 public:
136 virtual ~KeychainImpl();
137
138 Mutex* getKeychainMutex();
139 Mutex* getMutexForObject();
140
141 ReadWriteLock* getKeychainReadWriteLock();
142 void aboutToDestruct();
143
144 bool operator ==(const KeychainImpl &) const;
145
146 // Item calls
147 void add(Item &item);
148 void addCopy(Item &item);
149 void deleteItem(Item &item); // item must be persistent.
150
151 // Keychain calls
152 void create(UInt32 passwordLength, const void *inPassword);
153 void createWithBlob(CssmData &blob);
154 void create(ConstStringPtr inPassword);
155 void create();
156 void create(const ResourceControlContext *rcc);
157 void open();
158
159 // Locking and unlocking a keychain.
160 void lock();
161 void unlock();
162 void unlock(const CssmData &password);
163 void unlock(ConstStringPtr password); // @@@ This has a length limit, we should remove it.
164 void stash();
165 void stashCheck();
166
167 void getSettings(uint32 &outIdleTimeOut, bool &outLockOnSleep);
168 void setSettings(uint32 inIdleTimeOut, bool inLockOnSleep);
169
170 // Passing in NULL for either oldPassword or newPassword will cause them to be prompted for.
171 // To specify a zero length password in either case the oldPasswordLength or newPasswordLength
172 // value must be 0 and the oldPassword or newPassword must not be NULL.
173 void changePassphrase(UInt32 oldPasswordLength, const void *oldPassword,
174 UInt32 newPasswordLength, const void *newPassword);
175 void changePassphrase(ConstStringPtr oldPassword, ConstStringPtr newPassword);
176
177 void authenticate(const CSSM_ACCESS_CREDENTIALS *cred); // Does not do an unlock.
178
179 const char *name() const { return mDb->name(); }
180 UInt32 status() const;
181 bool exists();
182 bool isActive() const;
183
184 KCCursor createCursor(const SecKeychainAttributeList *attrList);
185 KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList);
186 CssmClient::Db database() { StLock<Mutex>_(mDbMutex); return mDb; }
187 DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); }
188
189 CssmClient::CSP csp();
190
191 PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId);
192
193 // This will make a primary key for this record type, and populate it completely from the given attributes
194 PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbAttributes *currentAttributes);
195 void gatherPrimaryKeyAttributes(CssmClient::DbAttributes& primaryKeyAttrs);
196
197 const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType);
198
199 Item item(const PrimaryKey& primaryKey);
200 Item item(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId);
201
202 // Check for an item that may have been deleted.
203 Item itemdeleted(const PrimaryKey& primaryKey);
204
205 CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag);
206 void getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info);
207 static void freeAttributeInfo(SecKeychainAttributeInfo *Info);
208 KeychainSchema keychainSchema();
209 void resetSchema();
210 void didDeleteItem(ItemImpl *inItemImpl);
211
212 void recode(const CssmData &data, const CssmData &extraData);
213 void copyBlob(CssmData &dbBlob);
214
215 void setBatchMode(Boolean mode, Boolean rollBack);
216
217 // yield default open() credentials for this keychain (as of now)
218 const AccessCredentials *defaultCredentials();
219
220 // Only call these functions while holding globals().apiLock.
221 bool inCache() const throw() { return mInCache; }
222 void inCache(bool inCache) throw() { mInCache = inCache; }
223
224 void postEvent(SecKeychainEvent kcEvent, ItemImpl* item);
225
226 void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl);
227
228 bool mayDelete();
229
230 // Returns true if this keychain supports the attribute integrity and
231 // partition ID protections
232 bool hasIntegrityProtection();
233
234 private:
235 // Checks for and triggers a keychain database upgrade
236 // DO NOT hold any of the keychain locks when you call this
237 bool performKeychainUpgradeIfNeeded();
238
239 // Attempt to upgrade this keychain's database
240 uint32 attemptKeychainMigration(uint32 oldBlobVersion, uint32 newBlobVersion);
241
242 // Remember if we've attempted to upgrade this keychain's database
243 bool mAttemptedUpgrade;
244
245 void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl);
246
247 // Use this when you want to be extra sure this item is removed from the
248 // cache. Iterates over the whole cache to find all instances. This function
249 // will take both cache map mutexes, so you must not hold only the
250 // mDbDeletedItemMapMutex when you call this function.
251 void forceRemoveFromCache(ItemImpl* inItemImpl);
252
253 ItemImpl *_lookupItem(const PrimaryKey &primaryKey);
254
255 // Looks up a deleted item in the deleted item map. Does not check the normal map.
256 ItemImpl *_lookupDeletedItemOnly(const PrimaryKey &primaryKey);
257
258 const AccessCredentials *makeCredentials();
259
260 typedef map<PrimaryKey, ItemImpl *> DbItemMap;
261 // Reference map of all items we know about that have a primaryKey
262 DbItemMap mDbItemMap;
263 Mutex mDbItemMapMutex;
264
265 // Reference map of all items we know about that have been deleted
266 // but we haven't yet received a deleted notification about.
267 // We need this for when we delete an item (and so don't want it anymore)
268 // but stil need the item around to pass along to the client process with the
269 // deletion notification (if they've registered for such things).
270 DbItemMap mDbDeletedItemMap;
271 Mutex mDbDeletedItemMapMutex;
272
273 // Note on ItemMapMutexes: STL maps are not thread-safe, so you must hold the
274 // mutex for the entire duration of your access/modification to the map.
275 // Otherwise, other processes might interrupt your iterator by adding/removing
276 // items. If you must hold both mutexes, you must take mDbItemMapMutex before
277 // mDbDeletedItemMapMutex.
278
279 // True iff we are in the cache of keychains in StorageManager
280 bool mInCache;
281
282 CssmClient::Db mDb;
283
284 KeychainSchema mKeychainSchema;
285
286 // Data for auto-unlock credentials
287 DefaultCredentials mCustomUnlockCreds;
288 bool mIsInBatchMode;
289 EventBuffer *mEventBuffer;
290 Mutex mMutex;
291
292 // Now that we sometimes change the database object, Db object
293 // creation/returning needs a mutex. You should only hold this if you're
294 // copying or changing the mDb object.
295 Mutex mDbMutex;
296
297 // Used to protect mDb across calls.
298 // Grab a read lock if you expect to read from this keychain in the future.
299 // The write lock is taken if we're replacing the database wholesale with something new.
300 ReadWriteLock mRWLock;
301 };
302
303
304 CFIndex GetKeychainRetainCount(Keychain& kc);
305
306 class Keychain : public SecPointer<KeychainImpl>
307 {
308 public:
309 Keychain();
310 Keychain(KeychainImpl *impl) : SecPointer<KeychainImpl>(impl) {}
311 ~Keychain();
312
313 static Keychain optional(SecKeychainRef handle);
314
315 private:
316 friend class StorageManager;
317 friend class KeychainImpl;
318 friend class TrustKeychains;
319 Keychain(const CssmClient::Db &db)
320 : SecPointer<KeychainImpl>(new KeychainImpl(db)) {}
321
322 typedef KeychainImpl Impl;
323 };
324
325
326 } // end namespace KeychainCore
327
328 } // end namespace Security
329
330 #endif // !_SECURITY_KEYCHAINS_H_