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 40class EventBuffer; 41 42namespace Security 43{ 44 45namespace KeychainCore 46{ 47 48class KCCursor; 49class Item; 50class PrimaryKey; 51class StorageManager; 52 53class KeychainSchemaImpl : public RefCount 54{ 55 NOCOPY(KeychainSchemaImpl) 56public: 57 friend class KeychainSchema; 58protected: 59 KeychainSchemaImpl(const CssmClient::Db &db); 60public: 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 81private: 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 90private: 91 const RelationInfoMap &relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const; 92}; 93 94 95class KeychainSchema : public RefPointer<KeychainSchemaImpl> 96{ 97public: 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 108private: 109 typedef KeychainSchemaImpl Impl; 110}; 111 112 113class ItemImpl; 114 115class KeychainImpl : public SecCFObject, private CssmClient::Db::DefaultCredentialsMaker 116{ 117 NOCOPY(KeychainImpl) 118public: 119 SECCFFUNCTIONS(KeychainImpl, SecKeychainRef, errSecInvalidKeychain, gTypes().KeychainImpl) 120 121 friend class Keychain; 122 friend class ItemImpl; 123protected: 124 KeychainImpl(const CssmClient::Db &db); 125 126protected: 127 // Methods called by ItemImpl; 128 void didUpdate(const Item &inItem, PrimaryKey &oldPK, 129 PrimaryKey &newPK); 130 void completeAdd(Item &item, PrimaryKey &key); 131 132public: 133 virtual ~KeychainImpl(); 134 135 Mutex* getKeychainMutex(); 136 Mutex* getMutexForObject(); 137 void aboutToDestruct(); 138 139 bool operator ==(const KeychainImpl &) const; 140 141 // Item calls 142 void add(Item &item); 143 void addCopy(Item &item); 144 void deleteItem(Item &item); // item must be persistant. 145 146 // Keychain calls 147 void create(UInt32 passwordLength, const void *inPassword); 148 void createWithBlob(CssmData &blob); 149 void create(ConstStringPtr inPassword); 150 void create(); 151 void create(const ResourceControlContext *rcc); 152 void open(); 153 154 // Locking and unlocking a keychain. 155 void lock(); 156 void unlock(); 157 void unlock(const CssmData &password); 158 void unlock(ConstStringPtr password); // @@@ This has a length limit, we should remove it. 159 void stash(); 160 void stashCheck(); 161 162 void getSettings(uint32 &outIdleTimeOut, bool &outLockOnSleep); 163 void setSettings(uint32 inIdleTimeOut, bool inLockOnSleep); 164 165 // Passing in NULL for either oldPassword or newPassword will cause them to be prompted for. 166 // To specify a zero length password in either case the oldPasswordLength or newPasswordLength 167 // value must be 0 and the oldPassword or newPassword must not be NULL. 168 void changePassphrase(UInt32 oldPasswordLength, const void *oldPassword, 169 UInt32 newPasswordLength, const void *newPassword); 170 void changePassphrase(ConstStringPtr oldPassword, ConstStringPtr newPassword); 171 172 void authenticate(const CSSM_ACCESS_CREDENTIALS *cred); // Does not do an unlock. 173 174 const char *name() const { return mDb->name(); } 175 UInt32 status() const; 176 bool exists(); 177 bool isActive() const; 178 179 KCCursor createCursor(const SecKeychainAttributeList *attrList); 180 KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList); 181 CssmClient::Db database() { return mDb; } 182 DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); } 183 184 CssmClient::CSP csp(); 185 186 PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); 187 void gatherPrimaryKeyAttributes(CssmClient::DbAttributes& primaryKeyAttrs); 188 189 const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType); 190 191 Item item(const PrimaryKey& primaryKey); 192 Item item(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); 193 194 CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag); 195 void getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info); 196 static void freeAttributeInfo(SecKeychainAttributeInfo *Info); 197 KeychainSchema keychainSchema(); 198 void resetSchema(); 199 void didDeleteItem(ItemImpl *inItemImpl); 200 201 void recode(const CssmData &data, const CssmData &extraData); 202 void copyBlob(CssmData &dbBlob); 203 204 void setBatchMode(Boolean mode, Boolean rollBack); 205 206 // yield default open() credentials for this keychain (as of now) 207 const AccessCredentials *defaultCredentials(); 208 209 // Only call these functions while holding globals().apiLock. 210 bool inCache() const throw() { return mInCache; } 211 void inCache(bool inCache) throw() { mInCache = inCache; } 212 213 void postEvent(SecKeychainEvent kcEvent, ItemImpl* item); 214 215 void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl); 216 217 bool mayDelete(); 218 219private: 220 void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl); 221 ItemImpl *_lookupItem(const PrimaryKey &primaryKey); 222 223 const AccessCredentials *makeCredentials(); 224 225 typedef map<PrimaryKey, __weak ItemImpl *> DbItemMap; 226 // Weak reference map of all items we know about that have a primaryKey 227 DbItemMap mDbItemMap; 228 // True iff we are in the cache of keychains in StorageManager 229 bool mInCache; 230 231 CssmClient::Db mDb; 232 233 KeychainSchema mKeychainSchema; 234 235 // Data for auto-unlock credentials 236 DefaultCredentials mCustomUnlockCreds; 237 bool mIsInBatchMode; 238 EventBuffer *mEventBuffer; 239 Mutex mMutex; 240}; 241 242 243CFIndex GetKeychainRetainCount(Keychain& kc); 244 245class Keychain : public SecPointer<KeychainImpl> 246{ 247public: 248 Keychain(); 249 Keychain(KeychainImpl *impl) : SecPointer<KeychainImpl>(impl) {} 250 ~Keychain(); 251 252 static Keychain optional(SecKeychainRef handle); 253 254private: 255 friend class StorageManager; 256 Keychain(const CssmClient::Db &db) 257 : SecPointer<KeychainImpl>(new KeychainImpl(db)) {} 258 259 typedef KeychainImpl Impl; 260}; 261 262 263} // end namespace KeychainCore 264 265} // end namespace Security 266 267#endif // !_SECURITY_KEYCHAINS_H_ 268