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