]> git.saurik.com Git - apple/security.git/blob - securityd/src/database.cpp
Security-57337.40.85.tar.gz
[apple/security.git] / securityd / src / database.cpp
1 /*
2 * Copyright (c) 2000-2008 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 //
26 // database - database session management
27 //
28 #include "database.h"
29 #include "agentquery.h"
30 #include "key.h"
31 #include "server.h"
32 #include "session.h"
33 #include "notifications.h"
34 #include <securityd_client/dictionary.h>
35 #include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
36 #include <security_cdsa_client/wrapkey.h>
37 #include <security_utilities/endian.h>
38
39 using namespace UnixPlusPlus;
40
41
42 //
43 // DbCommon basics
44 //
45 DbCommon::DbCommon(Session &session)
46 {
47 referent(session);
48 }
49
50 Session &DbCommon::session() const
51 {
52 return referent<Session>();
53 }
54
55
56 //
57 // Database basics
58 //
59 Database::Database(Process &proc)
60 {
61 referent(proc);
62 }
63
64
65 Process& Database::process() const
66 {
67 return referent<Process>();
68 }
69
70
71 //
72 // Send a keychain-related notification event about this database
73 //
74 void DbCommon::notify(NotificationEvent event, const DLDbIdentifier &ident)
75 {
76 // form the data (encoded DLDbIdentifier)
77 NameValueDictionary nvd;
78 NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier(ident, nvd);
79 CssmData data;
80 nvd.Export(data);
81
82 // inject notification into Security event system
83 Listener::notify(kNotificationDomainDatabase, event, data);
84
85 // clean up
86 free (data.data());
87 }
88
89
90 //
91 // Default behaviors
92 //
93 void DbCommon::sleepProcessing()
94 {
95 // nothing
96 }
97
98 void DbCommon::lockProcessing()
99 {
100 // nothing
101 }
102
103 bool DbCommon::belongsToSystem() const
104 {
105 return false;
106 }
107
108
109 void Database::releaseKey(Key &key)
110 {
111 kill(key);
112 }
113
114 void Database::releaseSearch(Search &search)
115 {
116 kill(search);
117 }
118
119 void Database::releaseRecord(Record &record)
120 {
121 kill(record);
122 }
123
124 void Database::dbName(const char *name)
125 {
126 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
127 }
128
129
130 //
131 // Functions that aren't implemented at the Database level but can stay that way
132 //
133 void Database::findFirst(const CssmQuery &query,
134 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
135 CssmData *data, RefPointer<Key> &key, RefPointer<Search> &search, RefPointer<Record> &record,
136 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
137 {
138 secdebug("database", "%p calling unimplemented findFirst", this);
139 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
140 }
141
142 void Database::findNext(Search *search,
143 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
144 CssmData *data, RefPointer<Key> &key, RefPointer<Record> &record,
145 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
146 {
147 secdebug("database", "%p calling unimplemented findNext", this);
148 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
149 }
150
151 void Database::findRecordHandle(Record *record,
152 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
153 CssmData *data, RefPointer<Key> &key,
154 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
155 {
156 secdebug("database", "%p calling unimplemented findRecordHandle", this);
157 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
158 }
159
160 void Database::insertRecord(CSSM_DB_RECORDTYPE recordtype,
161 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength,
162 const CssmData &data, RecordHandle &record)
163 {
164 secdebug("database", "%p calling unimplemented insertRecord", this);
165 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
166 }
167
168 void Database::modifyRecord(CSSM_DB_RECORDTYPE recordtype, Record *record,
169 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength,
170 const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode)
171 {
172 secdebug("database", "%p calling unimplemented modifyRecord", this);
173 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
174 }
175
176 void Database::deleteRecord(Database::Record *record)
177 {
178 secdebug("database", "%p calling unimplemented deleteRecord", this);
179 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
180 }
181
182 void Database::authenticate(CSSM_DB_ACCESS_TYPE, const AccessCredentials *)
183 {
184 secdebug("database", "%p calling unimplemented authenticate", this);
185 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
186 }
187
188 bool Database::checkCredentials(const AccessCredentials *)
189 {
190 secdebug("database", "%p calling unimplemented checkCredentials", this);
191 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
192 }
193
194 SecurityServerAcl &Database::acl()
195 {
196 secdebug("database", "%p has no ACL implementation", this);
197 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
198 }
199
200 bool Database::isLocked()
201 {
202 secdebug("database", "%p calling unimplemented isLocked", this);
203 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
204 }
205
206
207 //
208 // SecurityServerAcl personality implementation.
209 // This is the trivial (type coding) stuff. The hard stuff is virtually mixed in.
210 //
211 Database *Database::relatedDatabase()
212 {
213 return this;
214 }
215
216 AclKind Database::aclKind() const
217 {
218 return dbAcl;
219 }
220
221
222 //
223 // Remote validation is not, by default, supported
224 //
225 bool Database::validateSecret(const AclSubject *, const AccessCredentials *)
226 {
227 return false;
228 }
229
230
231 //
232 // Implementation of a "system keychain unlock key store"
233 //
234 SystemKeychainKey::SystemKeychainKey(const char *path)
235 : mPath(path), mValid(false)
236 {
237 // explicitly set up a key header for a raw 3DES key
238 CssmKey::Header &hdr = mKey.header();
239 hdr.blobType(CSSM_KEYBLOB_RAW);
240 hdr.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING);
241 hdr.keyClass(CSSM_KEYCLASS_SESSION_KEY);
242 hdr.algorithm(CSSM_ALGID_3DES_3KEY_EDE);
243 hdr.KeyAttr = 0;
244 hdr.KeyUsage = CSSM_KEYUSE_ANY;
245 mKey = CssmData::wrap(mBlob.masterKey);
246 }
247
248 SystemKeychainKey::~SystemKeychainKey()
249 {
250 }
251
252 bool SystemKeychainKey::matches(const DbBlob::Signature &signature)
253 {
254 return update() && signature == mBlob.signature;
255 }
256
257 bool SystemKeychainKey::update()
258 {
259 // if we checked recently, just assume it's okay
260 if (mValid && mUpdateThreshold > Time::now())
261 return mValid;
262
263 // check the file
264 struct stat st;
265 if (::stat(mPath.c_str(), &st)) {
266 // something wrong with the file; can't use it
267 mUpdateThreshold = Time::now() + Time::Interval(checkDelay);
268 return mValid = false;
269 }
270 if (mValid && Time::Absolute(st.st_mtimespec) == mCachedDate)
271 return true;
272 mUpdateThreshold = Time::now() + Time::Interval(checkDelay);
273
274 try {
275 secdebug("syskc", "reading system unlock record from %s", mPath.c_str());
276 AutoFileDesc fd(mPath, O_RDONLY);
277 if (fd.read(mBlob) != sizeof(mBlob))
278 return false;
279 if (mBlob.isValid()) {
280 mCachedDate = st.st_mtimespec;
281 return mValid = true;
282 } else
283 return mValid = false;
284 } catch (...) {
285 secdebug("syskc", "system unlock record not available");
286 return false;
287 }
288 }