]> git.saurik.com Git - apple/security.git/blob - libsecurity_cdsa_client/lib/dlclient.cpp
6fa631bf7495154abd48c66d472f1006c26657f8
[apple/security.git] / libsecurity_cdsa_client / lib / 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_cdsa_client/dlclient.h>
23 #include <security_cdsa_client/aclclient.h>
24 #include <Security/cssmapple.h>
25 #include <Security/cssmapplePriv.h>
26
27 using namespace CssmClient;
28
29
30 // blob type for blobs created by these classes -- done so that we can change the formats later
31 const uint32 kBlobType = 0x1;
32
33
34 //
35 // Abstract classes
36 //
37 DbMaker::~DbMaker()
38 { /* virtual */ }
39
40 DbCursorMaker::~DbCursorMaker()
41 { /* virtual */ }
42
43 DbUniqueRecordMaker::~DbUniqueRecordMaker()
44 { /* virtual */ }
45
46
47 //
48 // Manage DL attachments
49 //
50 DLImpl::DLImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_DL)
51 {
52 }
53
54 DLImpl::DLImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_DL)
55 {
56 }
57
58 DLImpl::~DLImpl()
59 {
60 }
61
62 void
63 DLImpl::getDbNames(char **)
64 {
65 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED);
66 }
67
68 void
69 DLImpl::freeNameList(char **)
70 {
71 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED);
72 }
73
74 DbImpl *
75 DLImpl::newDb(const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation)
76 {
77 return new DbImpl(DL(this), inDbName, inDbLocation);
78 }
79
80
81 //
82 // Db (database)
83 //
84 DbImpl::DbImpl(const DL &dl, const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation)
85 : ObjectImpl(dl), mDbName(inDbName, inDbLocation),
86 mUseNameFromHandle(!inDbName), mNameFromHandle(NULL),
87 mAccessRequest(CSSM_DB_ACCESS_READ), mAccessCredentials(NULL),
88 mDefaultCredentials(NULL), mOpenParameters(NULL), mDbInfo(NULL),
89 mResourceControlContext(NULL)
90 {
91 }
92
93 DbImpl::~DbImpl()
94 {
95 try
96 {
97 if (mNameFromHandle)
98 allocator().free(mNameFromHandle);
99 deactivate();
100 }
101 catch(...) {}
102 }
103
104 void
105 DbImpl::open()
106 {
107 if (!mActive)
108 {
109 assert(mDbInfo == nil);
110 mHandle.DLHandle = dl()->handle();
111 check(CSSM_DL_DbOpen(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(),
112 mAccessRequest, mAccessCredentials,
113 mOpenParameters, &mHandle.DBHandle));
114
115 StLock<Mutex> _(mActivateMutex);
116 mActive = true;
117
118 if (!mAccessCredentials && mDefaultCredentials)
119 if (const AccessCredentials *creds = mDefaultCredentials->makeCredentials())
120 CSSM_DL_Authenticate(handle(), mAccessRequest, creds); // ignore error
121 }
122 }
123
124 void
125 DbImpl::createWithBlob(CssmData &blob)
126 {
127 if (mActive)
128 CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS);
129
130 if (mDbInfo == nil) {
131 // handle a missing (null) mDbInfo as an all-zero one
132 static const CSSM_DBINFO nullDbInfo = { };
133 mDbInfo = &nullDbInfo;
134 }
135
136 mHandle.DLHandle = dl()->handle();
137
138 // create a parameter block for our call to the passthrough
139 CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS params;
140
141 params.dbName = mDbName.canonicalName ();
142 params.dbLocation = dbLocation ();
143 params.dbInfo = mDbInfo;
144 params.accessRequest = mAccessRequest;
145 params.credAndAclEntry = NULL;
146 params.openParameters = mOpenParameters;
147 params.blob = &blob;
148
149 check(CSSM_DL_PassThrough (mHandle, CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB, &params, (void**) &mHandle.DBHandle));
150 }
151
152 void
153 DbImpl::create()
154 {
155 StLock<Mutex> _(mActivateMutex);
156 if (mActive)
157 CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS);
158
159 if (mDbInfo == nil) {
160 // handle a missing (null) mDbInfo as an all-zero one
161 static const CSSM_DBINFO nullDbInfo = { };
162 mDbInfo = &nullDbInfo;
163 }
164 mHandle.DLHandle = dl()->handle();
165
166 if (!mResourceControlContext && mAccessCredentials) {
167 AclFactory::AnyResourceContext ctx(mAccessCredentials);
168 check(CSSM_DL_DbCreate(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(),
169 mDbInfo, mAccessRequest, &ctx,
170 mOpenParameters, &mHandle.DBHandle));
171 } else {
172 check(CSSM_DL_DbCreate(mHandle.DLHandle, mDbName.canonicalName(), dbLocation(),
173 mDbInfo, mAccessRequest, mResourceControlContext,
174 mOpenParameters, &mHandle.DBHandle));
175 }
176 mActive = true;
177 }
178
179 void
180 DbImpl::close()
181 {
182 StLock<Mutex> _(mActivateMutex);
183 if (mActive)
184 {
185 check(CSSM_DL_DbClose (mHandle));
186 mActive = false;
187 }
188 }
189
190 void
191 DbImpl::activate()
192 {
193 StLock<Mutex> _(mActivateMutex);
194 if (!mActive)
195 {
196 if (mDbInfo)
197 create();
198 else
199 open();
200 }
201 }
202
203 void
204 DbImpl::deactivate()
205 {
206 StLock<Mutex> _(mActivateMutex);
207 if (mActive)
208 {
209 mActive = false;
210 close();
211 }
212 }
213
214 void
215 DbImpl::deleteDb()
216 {
217 // Deactivate so the db gets closed if it was open.
218 deactivate();
219 // This call does not require the receiver to be active.
220 check(CSSM_DL_DbDelete(dl()->handle(), mDbName.canonicalName(), dbLocation(),
221 mAccessCredentials));
222 }
223
224 void
225 DbImpl::rename(const char *newName)
226 {
227 // Deactivate so the db gets closed if it was open.
228 deactivate();
229 if (::rename(mDbName.canonicalName(), newName))
230 UnixError::throwMe(errno);
231
232 // Change our DbName to reflect this rename.
233 mDbName = DbName(newName, dbLocation());
234 }
235
236 void
237 DbImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest,
238 const CSSM_ACCESS_CREDENTIALS *inAccessCredentials)
239 {
240 if (!mActive)
241 {
242 // XXX Could do the same for create but this would require sticking
243 // inAccessCredentials into mResourceControlContext.
244 if (!mDbInfo)
245 {
246 // We were not yet active. Just do an open.
247 accessRequest(inAccessRequest);
248 accessCredentials(inAccessCredentials);
249 activate();
250 return;
251 }
252 }
253
254 check(CSSM_DL_Authenticate(handle(), inAccessRequest, inAccessCredentials));
255 }
256
257 void
258 DbImpl::name(char *&outDbName)
259 {
260 check(CSSM_DL_GetDbNameFromHandle(handle(), &outDbName));
261 }
262
263 const char *
264 DbImpl::name()
265 {
266 if (mUseNameFromHandle)
267 {
268 if (mNameFromHandle
269 || !CSSM_DL_GetDbNameFromHandle(handle(), &mNameFromHandle))
270 {
271 return mNameFromHandle;
272 }
273
274 // We failed to get the name from the handle so use the passed
275 // in name instead
276 mUseNameFromHandle = false;
277 }
278
279 return mDbName.canonicalName();
280 }
281
282 void
283 DbImpl::createRelation(CSSM_DB_RECORDTYPE inRelationID,
284 const char *inRelationName,
285 uint32 inNumberOfAttributes,
286 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo,
287 uint32 inNumberOfIndexes,
288 const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo)
289 {
290 check(CSSM_DL_CreateRelation(handle(), inRelationID, inRelationName,
291 inNumberOfAttributes, pAttributeInfo,
292 inNumberOfIndexes, pIndexInfo));
293 }
294
295 void
296 DbImpl::destroyRelation(CSSM_DB_RECORDTYPE inRelationID)
297 {
298 check(CSSM_DL_DestroyRelation(handle(), inRelationID));
299 }
300
301 DbUniqueRecord
302 DbImpl::insert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
303 const CSSM_DATA *data)
304 {
305 DbUniqueRecord uniqueId(Db(this));
306 check(CSSM_DL_DataInsert(handle(), recordType,
307 attributes,
308 data, uniqueId));
309 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
310 uniqueId->activate();
311 return uniqueId;
312 }
313
314
315 DbUniqueRecord
316 DbImpl::insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
317 CSSM_DATA *data)
318 {
319 DbUniqueRecord uniqueId(Db(this));
320
321 // fill out the parameters
322 CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS params;
323 params.recordType = recordType;
324 params.attributes = const_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA*>(attributes);
325 params.data = *data;
326
327 // for clarity, call the overloaded operator to produce a unique record pointer
328 CSSM_DB_UNIQUE_RECORD_PTR *uniquePtr = uniqueId;
329
330 // make the call
331 passThrough (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION, &params, (void**) uniquePtr);
332
333 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
334 uniqueId->activate();
335 return uniqueId;
336 }
337
338
339 //
340 // Generic Passthrough interface
341 //
342 void DbImpl::passThrough(uint32 passThroughId, const void *in, void **out)
343 {
344 check(CSSM_DL_PassThrough(handle(), passThroughId, in, out));
345 }
346
347
348 //
349 // Passthrough functions (only implemented by AppleCSPDL).
350 //
351 void
352 DbImpl::lock()
353 {
354 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_LOCK, NULL, NULL));
355 }
356
357 void
358 DbImpl::unlock()
359 {
360 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, NULL, NULL));
361 }
362
363 void
364 DbImpl::unlock(const CSSM_DATA &password)
365 {
366 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, &password, NULL));
367 }
368
369 void
370 DbImpl::getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep)
371 {
372 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR settings;
373 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_SETTINGS,
374 NULL, reinterpret_cast<void **>(&settings)));
375 outIdleTimeout = settings->idleTimeout;
376 outLockOnSleep = settings->lockOnSleep;
377 allocator().free(settings);
378 }
379
380 void
381 DbImpl::setSettings(uint32 inIdleTimeout, bool inLockOnSleep)
382 {
383 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS settings;
384 settings.idleTimeout = inIdleTimeout;
385 settings.lockOnSleep = inLockOnSleep;
386 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_SET_SETTINGS, &settings, NULL));
387 }
388
389 bool
390 DbImpl::isLocked()
391 {
392 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params;
393 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_IS_LOCKED,
394 NULL, reinterpret_cast<void **>(&params)));
395 bool isLocked = params->isLocked;
396 allocator().free(params);
397 return isLocked;
398 }
399
400 void
401 DbImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred)
402 {
403 CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS params;
404 params.accessCredentials = const_cast<CSSM_ACCESS_CREDENTIALS *>(cred);
405 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_CHANGE_PASSWORD, &params, NULL));
406 }
407
408 void DbImpl::recode(const CSSM_DATA &data, const CSSM_DATA &extraData)
409 {
410 // setup parameters for the recode call
411 CSSM_APPLECSPDL_RECODE_PARAMETERS params;
412 params.dbBlob = data;
413 params.extraData = extraData;
414
415 // do the call
416 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_CSP_RECODE, &params, NULL));
417 }
418
419 void DbImpl::copyBlob (CssmData &data)
420 {
421 // do the call
422 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_COPY_BLOB, NULL, (void**) (CSSM_DATA*) &data));
423 }
424
425 void DbImpl::setBatchMode(Boolean mode, Boolean rollback)
426 {
427 //
428 // We need the DL_DB_Handle of the underyling DL in order to use CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT
429 //
430 CSSM_RETURN result;
431 CSSM_DL_DB_HANDLE dldbHandleOfUnderlyingDL;
432 result = CSSM_DL_PassThrough(handle(),
433 CSSM_APPLECSPDL_DB_GET_HANDLE,
434 NULL,
435 (void **)&dldbHandleOfUnderlyingDL);
436 //
437 // Now, toggle the autocommit...
438 //
439 if ( result == noErr )
440 {
441 CSSM_BOOL modeToUse = !mode;
442 if (rollback)
443 {
444 result = (OSStatus)CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL,
445 CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL);
446 }
447
448 result = CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL,
449 CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT,
450 (void *)(modeToUse),
451 NULL);
452 if (!rollback && modeToUse)
453 result = CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL,
454 CSSM_APPLEFILEDL_COMMIT,
455 NULL,
456 NULL);
457 }
458 }
459
460 //
461 // DbCursorMaker
462 //
463 DbCursorImpl *
464 DbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator)
465 {
466 return new DbDbCursorImpl(Db(this), query, allocator);
467 }
468
469 DbCursorImpl *
470 DbImpl::newDbCursor(uint32 capacity, Allocator &allocator)
471 {
472 return new DbDbCursorImpl(Db(this), capacity, allocator);
473 }
474
475
476 //
477 // Db adapters for AclBearer
478 //
479 void DbImpl::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const
480 {
481 aclInfos.allocator(allocator());
482 check(CSSM_DL_GetDbAcl(const_cast<DbImpl*>(this)->handle(),
483 reinterpret_cast<const CSSM_STRING *>(selectionTag), aclInfos, aclInfos));
484 }
485
486 void DbImpl::changeAcl(const CSSM_ACL_EDIT &aclEdit,
487 const CSSM_ACCESS_CREDENTIALS *accessCred)
488 {
489 check(CSSM_DL_ChangeDbAcl(handle(), AccessCredentials::needed(accessCred), &aclEdit));
490 }
491
492 void DbImpl::getOwner(AutoAclOwnerPrototype &owner) const
493 {
494 owner.allocator(allocator());
495 check(CSSM_DL_GetDbOwner(const_cast<DbImpl*>(this)->handle(), owner));
496 }
497
498 void DbImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner,
499 const CSSM_ACCESS_CREDENTIALS *accessCred)
500 {
501 check(CSSM_DL_ChangeDbOwner(handle(),
502 AccessCredentials::needed(accessCred), &newOwner));
503 }
504
505 void DbImpl::defaultCredentials(DefaultCredentialsMaker *maker)
506 {
507 mDefaultCredentials = maker;
508 }
509
510
511 //
512 // Abstract DefaultCredentialsMakers
513 //
514 DbImpl::DefaultCredentialsMaker::~DefaultCredentialsMaker()
515 { /* virtual */ }
516
517
518 //
519 // Db adapters for DLAccess
520 //
521 CSSM_HANDLE Db::dlGetFirst(const CSSM_QUERY &query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes,
522 CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id)
523 {
524 CSSM_HANDLE result;
525 switch (CSSM_RETURN rc = CSSM_DL_DataGetFirst(handle(), &query, &result, &attributes, data, &id)) {
526 case CSSM_OK:
527 return result;
528 case CSSMERR_DL_ENDOFDATA:
529 return CSSM_INVALID_HANDLE;
530 default:
531 CssmError::throwMe(rc);
532 return CSSM_INVALID_HANDLE; // placebo
533 }
534 }
535
536 bool Db::dlGetNext(CSSM_HANDLE query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes,
537 CSSM_DATA *data, CSSM_DB_UNIQUE_RECORD *&id)
538 {
539 CSSM_RETURN rc = CSSM_DL_DataGetNext(handle(), query, &attributes, data, &id);
540 switch (rc) {
541 case CSSM_OK:
542 return true;
543 case CSSMERR_DL_ENDOFDATA:
544 return false;
545 default:
546 CssmError::throwMe(rc);
547 return false; // placebo
548 }
549 }
550
551 void Db::dlAbortQuery(CSSM_HANDLE query)
552 {
553 CssmError::check(CSSM_DL_DataAbortQuery(handle(), query));
554 }
555
556 void Db::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id)
557 {
558 CssmError::check(CSSM_DL_FreeUniqueRecord(handle(), id));
559 }
560
561 void Db::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id)
562 {
563 CssmError::check(CSSM_DL_DataDelete(handle(), id));
564 }
565
566 Allocator &Db::allocator()
567 {
568 return Object::allocator();
569 }
570
571
572 //
573 // DbUniqueRecordMaker
574 //
575 DbUniqueRecordImpl *
576 DbImpl::newDbUniqueRecord()
577 {
578 return new DbUniqueRecordImpl(Db(this));
579 }
580
581
582 //
583 // Utility methods
584 //
585 DLDbIdentifier
586 DbImpl::dlDbIdentifier()
587 {
588 // Always use the same dbName and dbLocation that were passed in during
589 // construction
590 return DLDbIdentifier(dl()->subserviceUid(), mDbName.canonicalName(), dbLocation());
591 }
592
593
594 //
595 // DbDbCursorImpl
596 //
597 DbDbCursorImpl::DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, Allocator &allocator)
598 : DbCursorImpl(db, query, allocator), mResultsHandle(CSSM_INVALID_HANDLE)
599 {
600 }
601
602 DbDbCursorImpl::DbDbCursorImpl(const Db &db, uint32 capacity, Allocator &allocator)
603 : DbCursorImpl(db, capacity, allocator), mResultsHandle(CSSM_INVALID_HANDLE)
604 {
605 }
606
607 DbDbCursorImpl::~DbDbCursorImpl()
608 {
609 try
610 {
611 deactivate();
612 }
613 catch(...) {}
614 }
615
616 bool
617 DbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId)
618 {
619 if (attributes)
620 attributes->deleteValues();
621
622 if (data)
623 data->clear();
624
625 CSSM_RETURN result;
626 Db db(database());
627 DbUniqueRecord unique(db);
628 if (!mActive)
629 {
630 // ask the CSP/DL if the requested record type exists
631 CSSM_BOOL boolResult;
632 CSSM_DL_PassThrough(db->handle(), CSSM_APPLECSPDL_DB_RELATION_EXISTS, &RecordType, (void**) &boolResult);
633 if (!boolResult)
634 {
635 if (data != NULL)
636 {
637 data->invalidate();
638 }
639
640 return false;
641 }
642
643 result = CSSM_DL_DataGetFirst(db->handle(),
644 this,
645 &mResultsHandle,
646 attributes,
647 data,
648 unique);
649
650 StLock<Mutex> _(mActivateMutex);
651 if (result == CSSM_OK)
652 mActive = true;
653 else if (data != NULL)
654 data->invalidate ();
655 }
656 else
657 {
658 result = CSSM_DL_DataGetNext(db->handle(),
659 mResultsHandle,
660 attributes,
661 data,
662 unique);
663
664 if (result != CSSM_OK && data != NULL)
665 {
666 data->invalidate ();
667 }
668 }
669
670 if (result != CSSM_OK && attributes != NULL)
671 {
672 attributes->invalidate();
673 }
674
675 if (result == CSSMERR_DL_ENDOFDATA)
676 {
677 StLock<Mutex> _(mActivateMutex);
678 mActive = false;
679 return false;
680 }
681
682 check(result);
683
684 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
685 unique->activate();
686 uniqueId = unique;
687 return true;
688 }
689
690 void
691 DbDbCursorImpl::activate()
692 {
693 }
694
695 void
696 DbDbCursorImpl::deactivate()
697 {
698 StLock<Mutex> _(mActivateMutex);
699 if (mActive)
700 {
701 mActive = false;
702 check(CSSM_DL_DataAbortQuery(database()->handle(), mResultsHandle));
703 }
704 }
705
706
707 //
708 // DbCursorImpl
709 //
710 DbCursorImpl::DbCursorImpl(const Object &parent, const CSSM_QUERY &query, Allocator &allocator) :
711 ObjectImpl(parent), CssmAutoQuery(query, allocator)
712 {
713 }
714
715 DbCursorImpl::DbCursorImpl(const Object &parent, uint32 capacity, Allocator &allocator) :
716 ObjectImpl(parent), CssmAutoQuery(capacity, allocator)
717 {
718 }
719
720 Allocator &
721 DbCursorImpl::allocator() const
722 {
723 return ObjectImpl::allocator();
724 }
725
726 void
727 DbCursorImpl::allocator(Allocator &alloc)
728 {
729 ObjectImpl::allocator(alloc);
730 }
731
732
733 //
734 // DbUniqueRecord
735 //
736 DbUniqueRecordImpl::DbUniqueRecordImpl(const Db &db) : ObjectImpl(db), mDestroyID (false)
737 {
738 }
739
740 DbUniqueRecordImpl::~DbUniqueRecordImpl()
741 {
742 try
743 {
744 if (mDestroyID)
745 {
746 allocator ().free (mUniqueId);
747 }
748
749 deactivate();
750 }
751 catch(...) {}
752 }
753
754 void
755 DbUniqueRecordImpl::deleteRecord()
756 {
757 check(CSSM_DL_DataDelete(database()->handle(), mUniqueId));
758 }
759
760 void
761 DbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType,
762 const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
763 const CSSM_DATA *data,
764 CSSM_DB_MODIFY_MODE modifyMode)
765 {
766 check(CSSM_DL_DataModify(database()->handle(), recordType, mUniqueId,
767 attributes,
768 data, modifyMode));
769 }
770
771 void
772 DbUniqueRecordImpl::modifyWithoutEncryption(CSSM_DB_RECORDTYPE recordType,
773 const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes,
774 const CSSM_DATA *data,
775 CSSM_DB_MODIFY_MODE modifyMode)
776 {
777 // fill out the parameters
778 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS params;
779 params.recordType = recordType;
780 params.uniqueID = mUniqueId;
781 params.attributes = const_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA*>(attributes);
782 params.data = (CSSM_DATA*) data;
783 params.modifyMode = modifyMode;
784
785 // modify the data
786 check(CSSM_DL_PassThrough(database()->handle(),
787 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION,
788 &params,
789 NULL));
790 }
791
792 void
793 DbUniqueRecordImpl::get(DbAttributes *attributes,
794 ::CssmDataContainer *data)
795 {
796 if (attributes)
797 attributes->deleteValues();
798
799 if (data)
800 data->clear();
801
802 // @@@ Fix the allocators for attributes and data.
803 CSSM_RETURN result;
804 result = CSSM_DL_DataGetFromUniqueRecordId(database()->handle(), mUniqueId,
805 attributes,
806 data);
807
808 if (result != CSSM_OK)
809 {
810 if (attributes)
811 attributes->invalidate();
812 if (data != NULL) // the data returned is no longer valid
813 {
814 data->invalidate ();
815 }
816 }
817
818 check(result);
819 }
820
821 void
822 DbUniqueRecordImpl::getWithoutEncryption(DbAttributes *attributes,
823 ::CssmDataContainer *data)
824 {
825 if (attributes)
826 attributes->deleteValues();
827
828 if (data)
829 data->clear();
830
831 // @@@ Fix the allocators for attributes and data.
832 CSSM_RETURN result;
833
834 // make the parameter block
835 CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS params;
836 params.uniqueID = mUniqueId;
837 params.attributes = attributes;
838
839 // get the data
840 ::CssmDataContainer recordData;
841 result = CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION, &params,
842 (void**) data);
843 check (result);
844 }
845
846 void
847 DbUniqueRecordImpl::activate()
848 {
849 StLock<Mutex> _(mActivateMutex);
850 mActive = true;
851 }
852
853 void
854 DbUniqueRecordImpl::deactivate()
855 {
856 StLock<Mutex> _(mActivateMutex);
857 if (mActive)
858 {
859 mActive = false;
860 check(CSSM_DL_FreeUniqueRecord(database()->handle(), mUniqueId));
861 }
862 }
863
864 void
865 DbUniqueRecordImpl::getRecordIdentifier(CSSM_DATA &data)
866 {
867 check(CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER,
868 mUniqueId, (void**) &data));
869 }
870
871 void DbUniqueRecordImpl::setUniqueRecordPtr(CSSM_DB_UNIQUE_RECORD_PTR uniquePtr)
872 {
873 // clone the record
874 mUniqueId = (CSSM_DB_UNIQUE_RECORD_PTR) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD));
875 *mUniqueId = *uniquePtr;
876 mDestroyID = true;
877 }
878
879 //
880 // DbAttributes
881 //
882 DbAttributes::DbAttributes()
883 : CssmAutoDbRecordAttributeData(0, Allocator::standard(), Allocator::standard())
884 {
885 }
886
887 DbAttributes::DbAttributes(const Db &db, uint32 capacity, Allocator &allocator)
888 : CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator)
889 {
890 }