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