2  * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 // Keychains.h - The Keychain class 
  27 #ifndef _SECURITY_KEYCHAINS_H_ 
  28 #define _SECURITY_KEYCHAINS_H_ 
  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> 
  37 #include "SecCFTypes.h" 
  38 #include "defaultcreds.h" 
  45 namespace KeychainCore
 
  53 class KeychainSchemaImpl 
: public RefCount
 
  55         NOCOPY(KeychainSchemaImpl
) 
  57         friend class KeychainSchema
; 
  59     KeychainSchemaImpl(const CssmClient::Db 
&db
); 
  61     virtual ~KeychainSchemaImpl(); 
  63         CSSM_DB_ATTRIBUTE_FORMAT 
attributeFormatFor(CSSM_DB_RECORDTYPE recordType
, uint32 attributeId
) const; 
  64         const CssmAutoDbRecordAttributeInfo 
&primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType
) const; 
  66         bool operator <(const KeychainSchemaImpl 
&other
) const; 
  67         bool operator ==(const KeychainSchemaImpl 
&other
) const; 
  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; 
  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
); 
  82         typedef map
<CSSM_DB_RECORDTYPE
, CssmAutoDbRecordAttributeInfo 
*> PrimaryKeyInfoMap
; 
  83         PrimaryKeyInfoMap mPrimaryKeyInfoMap
; 
  85         typedef map
<uint32
, CSSM_DB_ATTRIBUTE_FORMAT
> RelationInfoMap
; 
  86         typedef map
<CSSM_DB_RECORDTYPE
, RelationInfoMap
> DatabaseInfoMap
; 
  87         DatabaseInfoMap mDatabaseInfoMap
; 
  91         const RelationInfoMap 
&relationInfoMapFor(CSSM_DB_RECORDTYPE recordType
) const; 
  95 class KeychainSchema 
: public RefPointer
<KeychainSchemaImpl
> 
  99     KeychainSchema(KeychainSchemaImpl 
*impl
) : RefPointer
<KeychainSchemaImpl
>(impl
) {} 
 100     KeychainSchema(const CssmClient::Db 
&db
) : RefPointer
<KeychainSchemaImpl
>(new KeychainSchemaImpl(db
)) {} 
 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
; } 
 109         typedef KeychainSchemaImpl Impl
; 
 115 class KeychainImpl 
: public SecCFObject
, private CssmClient::Db::DefaultCredentialsMaker
 
 119         SECCFFUNCTIONS(KeychainImpl
, SecKeychainRef
, errSecInvalidKeychain
, gTypes().KeychainImpl
) 
 121         friend class Keychain
; 
 122         friend class ItemImpl
; 
 123         friend class KeyItem
; 
 124     friend class KCCursorImpl
; 
 125     friend class StorageManager
; 
 127     KeychainImpl(const CssmClient::Db 
&db
); 
 130         // Methods called by ItemImpl; 
 131         void didUpdate(const Item 
&inItem
, PrimaryKey 
&oldPK
, 
 133         void completeAdd(Item 
&item
, PrimaryKey 
&key
); 
 136     virtual ~KeychainImpl(); 
 138         Mutex
* getKeychainMutex(); 
 139         Mutex
* getMutexForObject(); 
 141     ReadWriteLock
* getKeychainReadWriteLock(); 
 142         void aboutToDestruct(); 
 144         bool operator ==(const KeychainImpl 
&) const; 
 147         void add(Item 
&item
); 
 148         void addCopy(Item 
&item
); 
 149     void deleteItem(Item 
&item
); // item must be persistent. 
 152         void create(UInt32 passwordLength
, const void *inPassword
); 
 153         void createWithBlob(CssmData 
&blob
); 
 154     void create(ConstStringPtr inPassword
); 
 156     void create(const ResourceControlContext 
*rcc
); 
 159         // Locking and unlocking a keychain. 
 162         void unlock(const CssmData 
&password
); 
 163     void unlock(ConstStringPtr password
); // @@@ This has a length limit, we should remove it. 
 167         void getSettings(uint32 
&outIdleTimeOut
, bool &outLockOnSleep
); 
 168         void setSettings(uint32 inIdleTimeOut
, bool inLockOnSleep
); 
 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
); 
 177     void authenticate(const CSSM_ACCESS_CREDENTIALS 
*cred
);     // Does not do an unlock. 
 179         const char *name() const { return mDb
->name(); } 
 180         UInt32 
status() const; 
 182         bool isActive() const; 
 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(); } 
 189         CssmClient::CSP 
csp(); 
 191         PrimaryKey 
makePrimaryKey(CSSM_DB_RECORDTYPE recordType
, CssmClient::DbUniqueRecord 
&uniqueId
); 
 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
); 
 197         const CssmAutoDbRecordAttributeInfo 
&primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType
); 
 199     Item 
item(const PrimaryKey
& primaryKey
); 
 200     Item 
item(CSSM_DB_RECORDTYPE recordType
, CssmClient::DbUniqueRecord 
&uniqueId
); 
 202     // Check for an item that may have been deleted. 
 203     Item 
itemdeleted(const PrimaryKey
& primaryKey
); 
 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(); 
 210         void didDeleteItem(ItemImpl 
*inItemImpl
); 
 212         void recode(const CssmData 
&data
, const CssmData 
&extraData
); 
 213         void copyBlob(CssmData 
&dbBlob
); 
 215         void setBatchMode(Boolean mode
, Boolean rollBack
); 
 217         // yield default open() credentials for this keychain (as of now) 
 218         const AccessCredentials 
*defaultCredentials(); 
 220         // Only call these functions while holding globals().apiLock. 
 221         bool inCache() const throw() { return mInCache
; } 
 222         void inCache(bool inCache
) throw() { mInCache 
= inCache
; } 
 224         void postEvent(SecKeychainEvent kcEvent
, ItemImpl
* item
); 
 226         void addItem(const PrimaryKey 
&primaryKey
, ItemImpl 
*dbItemImpl
); 
 230     // Returns true if this keychain supports the attribute integrity and 
 231     // partition ID protections 
 232     bool hasIntegrityProtection(); 
 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(); 
 239     // Attempt to upgrade this keychain's database 
 240     uint32 
attemptKeychainMigration(uint32 oldBlobVersion
, uint32 newBlobVersion
); 
 242     // Remember if we've attempted to upgrade this keychain's database 
 243     bool mAttemptedUpgrade
; 
 245         void removeItem(const PrimaryKey 
&primaryKey
, ItemImpl 
*inItemImpl
); 
 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
); 
 253         ItemImpl 
*_lookupItem(const PrimaryKey 
&primaryKey
); 
 255     // Looks up a deleted item in the deleted item map. Does not check the normal map. 
 256     ItemImpl 
*_lookupDeletedItemOnly(const PrimaryKey 
&primaryKey
); 
 258         const AccessCredentials 
*makeCredentials(); 
 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
; 
 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
; 
 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. 
 279         // True iff we are in the cache of keychains in StorageManager 
 284         KeychainSchema mKeychainSchema
; 
 286         // Data for auto-unlock credentials 
 287         DefaultCredentials mCustomUnlockCreds
; 
 289         EventBuffer 
*mEventBuffer
; 
 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. 
 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
; 
 304 CFIndex 
GetKeychainRetainCount(Keychain
& kc
); 
 306 class Keychain 
: public SecPointer
<KeychainImpl
> 
 310     Keychain(KeychainImpl 
*impl
) : SecPointer
<KeychainImpl
>(impl
) {} 
 313         static Keychain 
optional(SecKeychainRef handle
);  
 316         friend class StorageManager
; 
 317     friend class KeychainImpl
; 
 318     friend class TrustKeychains
; 
 319     Keychain(const CssmClient::Db 
&db
) 
 320         : SecPointer
<KeychainImpl
>(new KeychainImpl(db
)) {} 
 322         typedef KeychainImpl Impl
; 
 326 } // end namespace KeychainCore 
 328 } // end namespace Security 
 330 #endif // !_SECURITY_KEYCHAINS_H_