--- /dev/null
+/*
+ * Copyright (c) 2000-2004,2011-2014 Apple 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 <security_cdsa_client/cspclient.h>
+#include <security_cdsa_client/dlclient.h>
+#include <security_utilities/refcount.h>
+#include <security_utilities/seccfobject.h>
+#include <Security/SecKeychain.h>
+#include <Security/SecKeychainItem.h>
+#include <memory>
+#include "SecCFTypes.h"
+#include "defaultcreds.h"
+
+class EventBuffer;
+
+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:
+ virtual ~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<CSSM_DB_RECORDTYPE, CssmAutoDbRecordAttributeInfo *> PrimaryKeyInfoMap;
+ PrimaryKeyInfoMap mPrimaryKeyInfoMap;
+
+ typedef map<uint32, CSSM_DB_ATTRIBUTE_FORMAT> RelationInfoMap;
+ typedef map<CSSM_DB_RECORDTYPE, RelationInfoMap> DatabaseInfoMap;
+ DatabaseInfoMap mDatabaseInfoMap;
+ Mutex mMutex;
+
+private:
+ const RelationInfoMap &relationInfoMapFor(CSSM_DB_RECORDTYPE recordType) const;
+};
+
+
+class KeychainSchema : public RefPointer<KeychainSchemaImpl>
+{
+public:
+ KeychainSchema() {}
+ KeychainSchema(KeychainSchemaImpl *impl) : RefPointer<KeychainSchemaImpl>(impl) {}
+ KeychainSchema(const CssmClient::Db &db) : RefPointer<KeychainSchemaImpl>(new KeychainSchemaImpl(db)) {}
+ ~KeychainSchema();
+
+ 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 ItemImpl;
+
+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);
+ void completeAdd(Item &item, PrimaryKey &key);
+
+public:
+ virtual ~KeychainImpl();
+
+ Mutex* getKeychainMutex();
+ Mutex* getMutexForObject();
+ void aboutToDestruct();
+
+ bool operator ==(const KeychainImpl &) const;
+
+ // Item calls
+ void add(Item &item);
+ void addCopy(Item &item);
+ void deleteItem(Item &item); // item must be persistant.
+
+ // Keychain calls
+ void create(UInt32 passwordLength, const void *inPassword);
+ void createWithBlob(CssmData &blob);
+ 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 stash();
+ void stashCheck();
+
+ 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 &data, const CssmData &extraData);
+ void copyBlob(CssmData &dbBlob);
+
+ void setBatchMode(Boolean mode, Boolean rollBack);
+
+ // 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; }
+
+ void postEvent(SecKeychainEvent kcEvent, ItemImpl* item);
+
+ void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl);
+
+ bool mayDelete();
+
+private:
+ void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl);
+ ItemImpl *_lookupItem(const PrimaryKey &primaryKey);
+
+ const AccessCredentials *makeCredentials();
+
+ typedef map<PrimaryKey, __weak ItemImpl *> 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;
+ bool mIsInBatchMode;
+ EventBuffer *mEventBuffer;
+ Mutex mMutex;
+};
+
+
+CFIndex GetKeychainRetainCount(Keychain& kc);
+
+class Keychain : public SecPointer<KeychainImpl>
+{
+public:
+ Keychain();
+ Keychain(KeychainImpl *impl) : SecPointer<KeychainImpl>(impl) {}
+ ~Keychain();
+
+ static Keychain optional(SecKeychainRef handle);
+
+private:
+ friend class StorageManager;
+ Keychain(const CssmClient::Db &db)
+ : SecPointer<KeychainImpl>(new KeychainImpl(db)) {}
+
+ typedef KeychainImpl Impl;
+};
+
+
+} // end namespace KeychainCore
+
+} // end namespace Security
+
+#endif // !_SECURITY_KEYCHAINS_H_