2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // database - database session management
25 #include "securityserver.h"
28 #include "notifications.h"
29 #include <Security/utilities.h>
30 #include <Security/handleobject.h>
31 #include <Security/cssmdb.h>
32 #include <Security/machserver.h>
33 #include "SecurityAgentClient.h"
34 #include <Security/timeflow.h>
42 using MachPlusPlus::MachServer
;
46 // A Database object represents an Apple CSP/DL open database (DL/DB) object.
47 // It maintains its protected semantic state (including keys) and provides controlled
50 class Database
: public HandleObject
, public SecurityServerAcl
{
51 static const Listener::Event lockedEvent
= Listener::lockedEvent
;
52 static const Listener::Event unlockedEvent
= Listener::unlockedEvent
;
53 static const Listener::Event passphraseChangedEvent
= Listener::passphraseChangedEvent
;
56 class Common
; friend class Common
;
58 Database(const DLDbIdentifier
&id
, const DBParameters
¶ms
, Process
&proc
,
59 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
);
64 static const int maxUnlockTryCount
= 3;
67 typedef DbBlob::Signature Signature
;
71 DbIdentifier(const DLDbIdentifier
&id
, Signature sig
)
72 : mIdent(id
), mSig(sig
) { }
74 operator const DLDbIdentifier
&() const { return mIdent
; }
75 operator const Signature
&() const { return mSig
; }
76 const char *dbName() const { return mIdent
.dbName(); }
78 bool operator < (const DbIdentifier
&id
) const // simple lexicographic
80 if (mIdent
< id
.mIdent
) return true;
81 if (id
.mIdent
< mIdent
) return false;
82 return mSig
< id
.mSig
;
86 DLDbIdentifier mIdent
;
91 class CommonMap
: public map
<DbIdentifier
, Common
*>, public Mutex
{
96 // A Database::Common is the "common core" of all Database objects that
97 // represent the same client database (on disk, presumably).
98 // NOTE: Common obeys exterior locking protocol: the caller (always Database)
99 // must lock it before operating on its non-const members. In practice,
100 // most Database methods lock down their Common first thing.
102 class Common
: public DatabaseCryptoCore
, public MachServer::Timer
, public Mutex
{
104 Common(const DbIdentifier
&id
, CommonMap
&pool
);
107 bool unlock(DbBlob
*blob
, void **privateAclBlob
= NULL
);
108 void lock(bool holdingCommonLock
, bool forSleep
= false); // versatile lock primitive
109 bool isLocked() const { return mIsLocked
; } // lock status
110 void activity(); // reset lock timeout
112 void makeNewSecrets();
114 const DbIdentifier
&identifier() const {return mIdentifier
; }
115 const DLDbIdentifier
&dlDbIdent() const { return identifier(); }
116 const char *dbName() const { return dlDbIdent().dbName(); }
118 DbBlob
*encode(Database
&db
);
121 void action(); // timer queue action to lock keychain
124 CommonMap
&pool
; // the CommonMap we belong to
126 DbIdentifier mIdentifier
; // database external identifier [const]
127 // all following data locked with object lock
128 uint32 sequence
; // change sequence number
129 DBParameters mParams
; // database parameters (arbitrated copy)
131 uint32 useCount
; // database sessions we belong to
132 uint32 version
; // version stamp for change tracking
135 bool mIsLocked
; // database is LOGICALLY locked
136 bool mValidParams
; // mParams has been set
139 const DbIdentifier
&identifier() const { return common
->identifier(); }
140 const char *dbName() const { return common
->dbName(); }
143 // encoding/decoding databases
145 Database(const DLDbIdentifier
&id
, const DbBlob
*blob
, Process
&proc
,
146 const AccessCredentials
*cred
);
147 void authenticate(const AccessCredentials
*cred
);
148 void changePassphrase(const AccessCredentials
*cred
);
149 Key
*extractMasterKey(Database
*db
,
150 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
151 uint32 usage
, uint32 attrs
);
152 void getDbIndex(CssmData
&indexData
);
154 // lock/unlock processing
155 void lock(); // unconditional lock
156 void unlock(); // full-feature unlock
157 void unlock(const CssmData
&passphrase
); // unlock with passphrase
159 bool decode(); // unlock given established master key
160 bool decode(const CssmData
&passphrase
); // set master key from PP, try unlock
162 bool validatePassphrase(const CssmData
&passphrase
) const; // nonthrowing validation
163 bool isLocked() const { return common
->isLocked(); } // lock status
165 void activity() const { common
->activity(); } // reset timeout clock
166 static void lockAllDatabases(CommonMap
&commons
, bool forSleep
= false); // lock all in session
168 // encoding/decoding keys
169 void decodeKey(KeyBlob
*blob
, CssmKey
&key
, void * &pubAcl
, void * &privAcl
);
170 KeyBlob
*encodeKey(const CssmKey
&key
, const CssmData
&pubAcl
, const CssmData
&privAcl
);
172 bool validBlob() const { return mBlob
&& version
== common
->version
; }
174 // manage database parameters
175 void setParameters(const DBParameters
¶ms
);
176 void getParameters(DBParameters
¶ms
);
178 // ACL state management hooks
179 void instantiateAcl();
181 const Database
*relatedDatabase() const; // "self", for SecurityServerAcl's sake
184 IFDUMP(void debugDump(const char *msg
));
187 void makeUnlocked(); // interior version of unlock()
188 void makeUnlocked(const AccessCredentials
*cred
); // like () with explicit cred
189 void makeUnlocked(const CssmData
&passphrase
); // interior version of unlock(CssmData)
191 void establishOldSecrets(const AccessCredentials
*creds
);
192 void establishNewSecrets(const AccessCredentials
*creds
, SecurityAgent::Reason reason
);
194 static CssmClient::Key
keyFromCreds(const TypedList
&sample
);
196 void encode(); // (re)generate mBlob if needed
198 static void discard(Common
*common
); // safely kill a Common
201 Common
*common
; // shared features of all instances of this database [const]
203 // all following data is locked by the common lock
204 bool mValidData
; // valid ACL and params (blob decoded)
206 uint32 version
; // version stamp for blob validity
207 DbBlob
*mBlob
; // database blob (encoded)
209 AccessCredentials
*mCred
; // local access credentials (always valid)
214 // This class implements a "system keychaiin unlock record" store
216 class SystemKeychainKey
{
218 SystemKeychainKey(const char *path
);
219 ~SystemKeychainKey();
221 bool matches(const DbBlob::Signature
&signature
);
222 CssmKey
&key() { return mKey
; }
225 std::string mPath
; // path to file
226 CssmKey mKey
; // proper CssmKey with data in mBlob
228 bool mValid
; // mBlob was validly read from mPath
229 UnlockBlob mBlob
; // contents of mPath as last read
231 Time::Absolute mCachedDate
; // modify date of file when last read
232 Time::Absolute mUpdateThreshold
; // cutoff threshold for checking again
234 static const int checkDelay
= 1; // seconds minimum delay between update checks