]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_client/dlclient.cpp
Security-30.1.tar.gz
[apple/security.git] / cdsa / cdsa_client / dlclient.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // dlclient - client interface to CSSM DLs and their operations
21 //
22 #include <Security/dlclient.h>
23
24 using namespace CssmClient;
25
26
27 //
28 // Manage DL attachments
29 //
30 DLImpl::DLImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_DL)
31 {
32 }
33
34 DLImpl::DLImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_DL)
35 {
36 }
37
38 DLImpl::~DLImpl()
39 {
40 }
41
42 void
43 DLImpl::getDbNames(char **)
44 {
45 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED);
46 }
47
48 void
49 DLImpl::freeNameList(char **)
50 {
51 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED);
52 }
53
54 DbImpl *
55 DLImpl::newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation)
56 {
57 return new DbImpl(DL(this), inDbName, inDbLocation);
58 }
59
60
61 //
62 // Db (database)
63 //
64 DbImpl::DbImpl(const DL &dl, const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation)
65 : ObjectImpl(dl), mDbName(inDbName, inDbLocation),
66 mAccessRequest(CSSM_DB_ACCESS_READ), mAccessCredentials(NULL),
67 mOpenParameters(NULL), mDbInfo(NULL), mResourceControlContext(NULL)
68 {
69 }
70
71 DbImpl::~DbImpl()
72 {
73 try
74 {
75 deactivate();
76 }
77 catch(...) {}
78 }
79
80 void
81 DbImpl::open()
82 {
83 if (!mActive)
84 {
85 assert(mDbInfo == nil);
86 mHandle.DLHandle = dl()->handle();
87 check(CSSM_DL_DbOpen(mHandle.DLHandle, name(), dbLocation(),
88 mAccessRequest, mAccessCredentials,
89 mOpenParameters, &mHandle.DBHandle));
90 mActive = true;
91 }
92 }
93
94 void
95 DbImpl::create()
96 {
97 if (mActive)
98 CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS);
99
100 assert(mDbInfo != nil);
101 mHandle.DLHandle = dl()->handle();
102 check(CSSM_DL_DbCreate(mHandle.DLHandle, name(), dbLocation(), mDbInfo,
103 mAccessRequest, mResourceControlContext,
104 mOpenParameters, &mHandle.DBHandle));
105 mActive = true;
106 }
107
108 void
109 DbImpl::close()
110 {
111 check(CSSM_DL_DbClose(mHandle));
112 }
113
114 void
115 DbImpl::activate()
116 {
117 if (!mActive)
118 {
119 if (mDbInfo)
120 create();
121 else
122 open();
123 }
124 }
125
126 void
127 DbImpl::deactivate()
128 {
129 if (mActive)
130 {
131 mActive = false;
132 close();
133 }
134 }
135
136 void
137 DbImpl::deleteDb()
138 {
139 // This call does not require the receiver to be active.
140 check(CSSM_DL_DbDelete(dl()->handle(), name(), dbLocation(),
141 mAccessCredentials));
142 }
143
144 void
145 DbImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest,
146 const CSSM_ACCESS_CREDENTIALS *inAccessCredentials)
147 {
148 if (!mActive)
149 {
150 // XXX Could do the same for create but this would require sticking
151 // inAccessCredentials into mResourceControlContext.
152 if (!mDbInfo)
153 {
154 // We were not yet active. Just do an open.
155 accessRequest(inAccessRequest);
156 accessCredentials(inAccessCredentials);
157 activate();
158 return;
159 }
160 }
161
162 check(CSSM_DL_Authenticate(handle(), inAccessRequest, inAccessCredentials));
163 }
164
165 void
166 DbImpl::name(char *&outDbName)
167 {
168 check(CSSM_DL_GetDbNameFromHandle(handle(), &outDbName));
169 }
170
171 void
172 DbImpl::createRelation(CSSM_DB_RECORDTYPE inRelationID,
173 const char *inRelationName,
174 uint32 inNumberOfAttributes,
175 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo,
176 uint32 inNumberOfIndexes,
177 const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo)
178 {
179 check(CSSM_DL_CreateRelation(handle(), inRelationID, inRelationName,
180 inNumberOfAttributes, pAttributeInfo,
181 inNumberOfIndexes, pIndexInfo));
182 }
183
184 void
185 DbImpl::destroyRelation(CSSM_DB_RECORDTYPE inRelationID)
186 {
187 check(CSSM_DL_DestroyRelation(handle(), inRelationID));
188 }
189
190 DbUniqueRecord
191 DbImpl::insert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
192 const CSSM_DATA *data)
193 {
194 DbUniqueRecord uniqueId(Db(this));
195 check(CSSM_DL_DataInsert(handle(), recordType,
196 attributes,
197 data, uniqueId));
198 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
199 uniqueId->activate();
200 return uniqueId;
201 }
202
203 #if 0
204 // @@@ These methods have been moved to DbUniqueRecord.
205 void
206 DbImpl::deleteRecord(const DbUniqueRecord &uniqueId)
207 {
208 check(CSSM_DL_DataDelete(handle(), uniqueId));
209 }
210
211 void
212 DbImpl::modify(CSSM_DB_RECORDTYPE recordType, DbUniqueRecord &uniqueId,
213 const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
214 const CSSM_DATA *data,
215 CSSM_DB_MODIFY_MODE modifyMode)
216 {
217 check(CSSM_DL_DataModify(handle(), recordType, uniqueId,
218 attributes,
219 data, modifyMode));
220 }
221
222 void
223 DbImpl::get(const DbUniqueRecord &uniqueId, DbAttributes *attributes,
224 ::CssmDataContainer *data)
225 {
226 if (attributes)
227 attributes->deleteValues();
228
229 if (data)
230 data->clear();
231
232 // @@@ Fix the const_cast here.
233 check(CSSM_DL_DataGetFromUniqueRecordId(handle(), uniqueId,
234 attributes,
235 data));
236 }
237 #endif
238
239 //
240 // Passthrough functions (only implemented by AppleCSPDL).
241 //
242 void
243 DbImpl::lock()
244 {
245 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_LOCK, NULL, NULL));
246 }
247
248 void
249 DbImpl::unlock()
250 {
251 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, NULL, NULL));
252 }
253
254 void
255 DbImpl::unlock(const CSSM_DATA &password)
256 {
257 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, &password, NULL));
258 }
259
260 void
261 DbImpl::getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep)
262 {
263 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR settings;
264 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_SETTINGS,
265 NULL, reinterpret_cast<void **>(&settings)));
266 outIdleTimeout = settings->idleTimeout;
267 outLockOnSleep = settings->lockOnSleep;
268 allocator().free(settings);
269 }
270
271 void
272 DbImpl::setSettings(uint32 inIdleTimeout, bool inLockOnSleep)
273 {
274 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS settings;
275 settings.idleTimeout = inIdleTimeout;
276 settings.lockOnSleep = inLockOnSleep;
277 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_SET_SETTINGS, &settings, NULL));
278 }
279
280 bool
281 DbImpl::isLocked()
282 {
283 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params;
284 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_IS_LOCKED,
285 NULL, reinterpret_cast<void **>(&params)));
286 bool isLocked = params->isLocked;
287 allocator().free(params);
288 return isLocked;
289 }
290
291 void
292 DbImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred)
293 {
294 CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS params;
295 params.accessCredentials = const_cast<CSSM_ACCESS_CREDENTIALS *>(cred);
296 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_CHANGE_PASSWORD, &params, NULL));
297 }
298
299
300 //
301 // DbCursorMaker
302 //
303 DbCursorImpl *
304 DbImpl::newDbCursor(const CSSM_QUERY &query, CssmAllocator &allocator)
305 {
306 return new DbDbCursorImpl(Db(this), query, allocator);
307 }
308
309 DbCursorImpl *
310 DbImpl::newDbCursor(uint32 capacity, CssmAllocator &allocator)
311 {
312 return new DbDbCursorImpl(Db(this), capacity, allocator);
313 }
314
315 //
316 // DbUniqueRecordMaker
317 //
318 DbUniqueRecordImpl *
319 DbImpl::newDbUniqueRecord()
320 {
321 return new DbUniqueRecordImpl(Db(this));
322 }
323
324
325 //
326 // Utility methods
327 //
328 DLDbIdentifier
329 DbImpl::dlDbIdentifier() const
330 {
331 return DLDbIdentifier(dl()->subserviceUid(), name(), dbLocation());
332 }
333
334
335 //
336 // DbDbCursorImpl
337 //
338 DbDbCursorImpl::DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, CssmAllocator &allocator)
339 : DbCursorImpl(db, query, allocator), mResultsHandle(CSSM_INVALID_HANDLE)
340 {
341 }
342
343 DbDbCursorImpl::DbDbCursorImpl(const Db &db, uint32 capacity, CssmAllocator &allocator)
344 : DbCursorImpl(db, capacity, allocator), mResultsHandle(CSSM_INVALID_HANDLE)
345 {
346 }
347
348 DbDbCursorImpl::~DbDbCursorImpl()
349 {
350 try
351 {
352 deactivate();
353 }
354 catch(...) {}
355 }
356
357 bool
358 DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId)
359 {
360 if (attributes)
361 attributes->deleteValues();
362
363 if (data)
364 data->clear();
365
366 CSSM_RETURN result;
367 Db db(database());
368 DbUniqueRecord unique(db);
369 if (!mActive)
370 {
371 result = CSSM_DL_DataGetFirst(db->handle(),
372 this,
373 &mResultsHandle,
374 attributes,
375 data,
376 unique);
377 if (result == CSSM_OK)
378 mActive = true;
379 }
380 else
381 {
382 result = CSSM_DL_DataGetNext(db->handle(),
383 mResultsHandle,
384 attributes,
385 data,
386 unique);
387 }
388
389 if (result == CSSMERR_DL_ENDOFDATA)
390 {
391 mActive = false;
392 return false;
393 }
394
395 check(result);
396
397 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
398 unique->activate();
399 uniqueId = unique;
400 return true;
401 }
402
403 void
404 DbDbCursorImpl::activate()
405 {
406 }
407
408 void
409 DbDbCursorImpl::deactivate()
410 {
411 if (mActive)
412 {
413 mActive = false;
414 check(CSSM_DL_DataAbortQuery(database()->handle(), mResultsHandle));
415 }
416 }
417
418
419 //
420 // DbCursorImpl
421 //
422 DbCursorImpl::DbCursorImpl(const Object &parent, const CSSM_QUERY &query, CssmAllocator &allocator) :
423 ObjectImpl(parent), CssmAutoQuery(query, allocator)
424 {
425 }
426
427 DbCursorImpl::DbCursorImpl(const Object &parent, uint32 capacity, CssmAllocator &allocator) :
428 ObjectImpl(parent), CssmAutoQuery(capacity, allocator)
429 {
430 }
431
432
433 //
434 // DbUniqueRecord
435 //
436 DbUniqueRecordImpl::DbUniqueRecordImpl(const Db &db) : ObjectImpl(db)
437 {
438 }
439
440 DbUniqueRecordImpl::~DbUniqueRecordImpl()
441 {
442 try
443 {
444 deactivate();
445 }
446 catch(...) {}
447 }
448
449 void
450 DbUniqueRecordImpl::deleteRecord()
451 {
452 check(CSSM_DL_DataDelete(database()->handle(), mUniqueId));
453 }
454
455 void
456 DbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType,
457 const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
458 const CSSM_DATA *data,
459 CSSM_DB_MODIFY_MODE modifyMode)
460 {
461 check(CSSM_DL_DataModify(database()->handle(), recordType, mUniqueId,
462 attributes,
463 data, modifyMode));
464 }
465
466 void
467 DbUniqueRecordImpl::get(DbAttributes *attributes,
468 ::CssmDataContainer *data)
469 {
470 if (attributes)
471 attributes->deleteValues();
472
473 if (data)
474 data->clear();
475
476 // @@@ Fix the allocators for attributes and data.
477 check(CSSM_DL_DataGetFromUniqueRecordId(database()->handle(), mUniqueId,
478 attributes,
479 data));
480 }
481
482 void
483 DbUniqueRecordImpl::activate()
484 {
485 mActive = true;
486 }
487
488 void
489 DbUniqueRecordImpl::deactivate()
490 {
491 if (mActive)
492 {
493 mActive = false;
494 check(CSSM_DL_FreeUniqueRecord(database()->handle(), mUniqueId));
495 }
496 }
497
498
499 //
500 // DbAttributes
501 //
502 DbAttributes::DbAttributes()
503 : CssmAutoDbRecordAttributeData(0, CssmAllocator::standard(), CssmAllocator::standard())
504 {
505 }
506
507 DbAttributes::DbAttributes(const Db &db, uint32 capacity, CssmAllocator &allocator)
508 : CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator)
509 {
510 }