/* * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // Keychains.h - The Keychain class // #ifndef _SECURITY_KEYCHAINS_H_ #define _SECURITY_KEYCHAINS_H_ #include #include #include #include #include #include #include #include "SecCFTypes.h" #include "defaultcreds.h" namespace Security { namespace KeychainCore { class KCCursor; class Item; class PrimaryKey; class StorageManager; class KeychainSchemaImpl : public RefCount { NOCOPY(KeychainSchemaImpl) public: friend class KeychainSchema; protected: KeychainSchemaImpl(const CssmClient::Db &db); public: ~KeychainSchemaImpl(); CSSM_DB_ATTRIBUTE_FORMAT attributeFormatFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) const; bool operator <(const KeychainSchemaImpl &other) const; bool operator ==(const KeychainSchemaImpl &other) const; void getAttributeInfoForRecordType(CSSM_DB_RECORDTYPE recordType, SecKeychainAttributeInfo **Info) const; CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; bool hasAttribute(CSSM_DB_RECORDTYPE recordType, uint32 attributeId) const; bool hasRecordType(CSSM_DB_RECORDTYPE recordType) const; void didCreateRelation(CSSM_DB_RECORDTYPE inRelationID, const char *inRelationName, uint32 inNumberOfAttributes, const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, uint32 inNumberOfIndexes, const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo); private: typedef map PrimaryKeyInfoMap; PrimaryKeyInfoMap mPrimaryKeyInfoMap; typedef map RelationInfoMap; typedef map DatabaseInfoMap; DatabaseInfoMap mDatabaseInfoMap; private: const RelationInfoMap &relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const; }; class KeychainSchema : public RefPointer { public: KeychainSchema() {} KeychainSchema(KeychainSchemaImpl *impl) : RefPointer(impl) {} KeychainSchema(const CssmClient::Db &db) : RefPointer(new KeychainSchemaImpl(db)) {} bool operator <(const KeychainSchema &other) const { return ptr && other.ptr ? *ptr < *other.ptr : ptr < other.ptr; } bool operator ==(const KeychainSchema &other) const { return ptr && other.ptr ? *ptr == *other.ptr : ptr == other.ptr; } private: typedef KeychainSchemaImpl Impl; }; class KeychainImpl : public SecCFObject, private CssmClient::Db::DefaultCredentialsMaker { NOCOPY(KeychainImpl) public: SECCFFUNCTIONS(KeychainImpl, SecKeychainRef, errSecInvalidKeychain, gTypes().KeychainImpl) friend class Keychain; friend class ItemImpl; protected: KeychainImpl(const CssmClient::Db &db); protected: // Methods called by ItemImpl; void didUpdate(const Item &inItem, PrimaryKey &oldPK, PrimaryKey &newPK); public: virtual ~KeychainImpl() throw(); bool operator ==(const KeychainImpl &) const; // Item calls void add(Item &item); void deleteItem(Item &item); // item must be persistant. // Keychain calls void create(UInt32 passwordLength, const void *inPassword); void create(ConstStringPtr inPassword); void create(); void create(const ResourceControlContext *rcc); void open(); // Locking and unlocking a keychain. void lock(); void unlock(); void unlock(const CssmData &password); void unlock(ConstStringPtr password); // @@@ This has a length limit, we should remove it. void getSettings(uint32 &outIdleTimeOut, bool &outLockOnSleep); void setSettings(uint32 inIdleTimeOut, bool inLockOnSleep); // Passing in NULL for either oldPassword or newPassword will cause them to be prompted for. // To specify a zero length password in either case the oldPasswordLength or newPasswordLength // value must be 0 and the oldPassword or newPassword must not be NULL. void changePassphrase(UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword); void changePassphrase(ConstStringPtr oldPassword, ConstStringPtr newPassword); void authenticate(const CSSM_ACCESS_CREDENTIALS *cred); // Does not do an unlock. const char *name() const { return mDb->name(); } UInt32 status() const; bool exists(); bool isActive() const; KCCursor createCursor(const SecKeychainAttributeList *attrList); KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList); CssmClient::Db database() { return mDb; } DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); } CssmClient::CSP csp(); PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); void gatherPrimaryKeyAttributes(CssmClient::DbAttributes& primaryKeyAttrs); const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType); Item item(const PrimaryKey& primaryKey); Item item(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag); void getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info); static void freeAttributeInfo(SecKeychainAttributeInfo *Info); KeychainSchema keychainSchema(); void resetSchema(); void didDeleteItem(ItemImpl *inItemImpl); void recode(const CssmData &dbBlob, const CssmData &data); void copyBlob(CssmData &dbBlob); // yield default open() credentials for this keychain (as of now) const AccessCredentials *defaultCredentials(); // Only call these functions while holding globals().apiLock. bool inCache() const throw() { return mInCache; } void inCache(bool inCache) throw() { mInCache = inCache; } private: void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl); void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl); ItemImpl *_lookupItem(const PrimaryKey &primaryKey); const AccessCredentials *makeCredentials(); // mDbItemMap and mInCache are protected by // globals().apiLock typedef map DbItemMap; // Weak reference map of all items we know about that have a primaryKey DbItemMap mDbItemMap; // True iff we are in the cache of keychains in StorageManager bool mInCache; CssmClient::Db mDb; KeychainSchema mKeychainSchema; // Data for auto-unlock credentials DefaultCredentials mCustomUnlockCreds; }; class Keychain : public SecPointer { public: Keychain() {} Keychain(KeychainImpl *impl) : SecPointer(impl) {} static Keychain optional(SecKeychainRef handle); private: friend class StorageManager; Keychain(const CssmClient::Db &db) : SecPointer(new KeychainImpl(db)) {} typedef KeychainImpl Impl; }; } // end namespace KeychainCore } // end namespace Security #endif // !_SECURITY_KEYCHAINS_H_