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