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