2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
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
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.
20 // dlclient - client interface to CSSM DLs and their operations
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 #include <security_cdsa_utilities/Schema.h>
29 using namespace CssmClient
;
31 #pragma clang diagnostic push
32 #pragma clang diagnostic ignored "-Wunused-const-variable"
33 // blob type for blobs created by these classes -- done so that we can change the formats later
34 const uint32 kBlobType
= 0x1;
35 #pragma clang diagnostic pop
43 DbCursorMaker::~DbCursorMaker()
46 DbUniqueRecordMaker::~DbUniqueRecordMaker()
51 // Manage DL attachments
53 DLImpl::DLImpl(const Guid
&guid
) : AttachmentImpl(guid
, CSSM_SERVICE_DL
)
57 DLImpl::DLImpl(const Module
&module) : AttachmentImpl(module, CSSM_SERVICE_DL
)
66 DLImpl::getDbNames(char **)
68 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED
);
72 DLImpl::freeNameList(char **)
74 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED
);
78 DLImpl::newDb(const char *inDbName
, const CSSM_NET_ADDRESS
*inDbLocation
)
80 return new DbImpl(DL(this), inDbName
, inDbLocation
);
87 DbImpl::DbImpl(const DL
&dl
, const char *inDbName
, const CSSM_NET_ADDRESS
*inDbLocation
)
88 : ObjectImpl(dl
), mDbName(inDbName
, inDbLocation
),
89 mUseNameFromHandle(!inDbName
), mNameFromHandle(NULL
),
90 mAccessRequest(CSSM_DB_ACCESS_READ
), mAccessCredentials(NULL
),
91 mDefaultCredentials(NULL
), mOpenParameters(NULL
), mDbInfo(NULL
),
92 mResourceControlContext(NULL
)
101 allocator().free(mNameFromHandle
);
111 StLock
<Mutex
> _(mActivateMutex
);
114 assert(mDbInfo
== nil
);
115 mHandle
.DLHandle
= dl()->handle();
116 check(CSSM_DL_DbOpen(mHandle
.DLHandle
, mDbName
.canonicalName(), dbLocation(),
117 mAccessRequest
, mAccessCredentials
,
118 mOpenParameters
, &mHandle
.DBHandle
));
124 if (!mAccessCredentials
&& mDefaultCredentials
)
125 if (const AccessCredentials
*creds
= mDefaultCredentials
->makeCredentials())
126 CSSM_DL_Authenticate(handle(), mAccessRequest
, creds
); // ignore error
130 DbImpl::createWithBlob(CssmData
&blob
)
133 CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS
);
135 if (mDbInfo
== nil
) {
136 // handle a missing (null) mDbInfo as an all-zero one
137 static const CSSM_DBINFO nullDbInfo
= { };
138 mDbInfo
= &nullDbInfo
;
141 mHandle
.DLHandle
= dl()->handle();
143 // create a parameter block for our call to the passthrough
144 CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS params
;
146 params
.dbName
= mDbName
.canonicalName ();
147 params
.dbLocation
= dbLocation ();
148 params
.dbInfo
= mDbInfo
;
149 params
.accessRequest
= mAccessRequest
;
150 params
.credAndAclEntry
= NULL
;
151 params
.openParameters
= mOpenParameters
;
154 check(CSSM_DL_PassThrough (mHandle
, CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB
, ¶ms
, (void**) &mHandle
.DBHandle
));
160 StLock
<Mutex
> _(mActivateMutex
);
162 CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS
);
164 if (mDbInfo
== nil
) {
165 // handle a missing (null) mDbInfo as an all-zero one
166 static const CSSM_DBINFO nullDbInfo
= { };
167 mDbInfo
= &nullDbInfo
;
169 mHandle
.DLHandle
= dl()->handle();
171 if (!mResourceControlContext
&& mAccessCredentials
) {
172 AclFactory::AnyResourceContext
ctx(mAccessCredentials
);
173 check(CSSM_DL_DbCreate(mHandle
.DLHandle
, mDbName
.canonicalName(), dbLocation(),
174 mDbInfo
, mAccessRequest
, &ctx
,
175 mOpenParameters
, &mHandle
.DBHandle
));
177 check(CSSM_DL_DbCreate(mHandle
.DLHandle
, mDbName
.canonicalName(), dbLocation(),
178 mDbInfo
, mAccessRequest
, mResourceControlContext
,
179 mOpenParameters
, &mHandle
.DBHandle
));
187 StLock
<Mutex
> _(mActivateMutex
);
190 check(CSSM_DL_DbClose (mHandle
));
210 StLock
<Mutex
> _(mActivateMutex
);
221 // Deactivate so the db gets closed if it was open.
223 // This call does not require the receiver to be active.
224 check(CSSM_DL_DbDelete(dl()->handle(), mDbName
.canonicalName(), dbLocation(),
225 mAccessCredentials
));
229 DbImpl::rename(const char *newName
)
231 // Deactivate so the db gets closed if it was open.
233 if (::rename(mDbName
.canonicalName(), newName
))
234 UnixError::throwMe(errno
);
236 // Change our DbName to reflect this rename.
237 mDbName
= DbName(newName
, dbLocation());
241 DbImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest
,
242 const CSSM_ACCESS_CREDENTIALS
*inAccessCredentials
)
246 // XXX Could do the same for create but this would require sticking
247 // inAccessCredentials into mResourceControlContext.
250 // We were not yet active. Just do an open.
251 accessRequest(inAccessRequest
);
252 accessCredentials(inAccessCredentials
);
258 check(CSSM_DL_Authenticate(handle(), inAccessRequest
, inAccessCredentials
));
262 DbImpl::name(char *&outDbName
)
264 check(CSSM_DL_GetDbNameFromHandle(handle(), &outDbName
));
270 if (mUseNameFromHandle
)
273 || !CSSM_DL_GetDbNameFromHandle(handle(), &mNameFromHandle
))
275 return mNameFromHandle
;
278 // We failed to get the name from the handle so use the passed
280 mUseNameFromHandle
= false;
283 return mDbName
.canonicalName();
287 DbImpl::createRelation(CSSM_DB_RECORDTYPE inRelationID
,
288 const char *inRelationName
,
289 uint32 inNumberOfAttributes
,
290 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO
*pAttributeInfo
,
291 uint32 inNumberOfIndexes
,
292 const CSSM_DB_SCHEMA_INDEX_INFO
*pIndexInfo
)
294 check(CSSM_DL_CreateRelation(handle(), inRelationID
, inRelationName
,
295 inNumberOfAttributes
, pAttributeInfo
,
296 inNumberOfIndexes
, pIndexInfo
));
300 DbImpl::destroyRelation(CSSM_DB_RECORDTYPE inRelationID
)
302 check(CSSM_DL_DestroyRelation(handle(), inRelationID
));
306 DbImpl::insert(CSSM_DB_RECORDTYPE recordType
, const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
307 const CSSM_DATA
*data
)
309 DbUniqueRecord
uniqueId(Db(this));
310 check(CSSM_DL_DataInsert(handle(), recordType
,
313 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
314 uniqueId
->activate();
320 DbImpl::insertWithoutEncryption(CSSM_DB_RECORDTYPE recordType
, const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
323 DbUniqueRecord
uniqueId(Db(this));
325 // fill out the parameters
326 CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS params
;
327 params
.recordType
= recordType
;
328 params
.attributes
= const_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA
*>(attributes
);
331 // for clarity, call the overloaded operator to produce a unique record pointer
332 CSSM_DB_UNIQUE_RECORD_PTR
*uniquePtr
= uniqueId
;
335 passThrough (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION
, ¶ms
, (void**) uniquePtr
);
337 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
338 uniqueId
->activate();
344 // Generic Passthrough interface
346 void DbImpl::passThrough(uint32 passThroughId
, const void *in
, void **out
)
348 check(CSSM_DL_PassThrough(handle(), passThroughId
, in
, out
));
353 // Passthrough functions (only implemented by AppleCSPDL).
358 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_LOCK
, NULL
, NULL
));
364 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK
, NULL
, NULL
));
368 DbImpl::unlock(const CSSM_DATA
&password
)
370 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK
, &password
, NULL
));
376 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_STASH
, NULL
, NULL
));
382 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_STASH_CHECK
, NULL
, NULL
));
386 DbImpl::getSettings(uint32
&outIdleTimeout
, bool &outLockOnSleep
)
388 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR settings
;
389 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_SETTINGS
,
390 NULL
, reinterpret_cast<void **>(&settings
)));
391 outIdleTimeout
= settings
->idleTimeout
;
392 outLockOnSleep
= settings
->lockOnSleep
;
393 allocator().free(settings
);
397 DbImpl::setSettings(uint32 inIdleTimeout
, bool inLockOnSleep
)
399 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS settings
;
400 settings
.idleTimeout
= inIdleTimeout
;
401 settings
.lockOnSleep
= inLockOnSleep
;
402 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_SET_SETTINGS
, &settings
, NULL
));
408 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params
;
409 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_IS_LOCKED
,
410 NULL
, reinterpret_cast<void **>(¶ms
)));
411 bool isLocked
= params
->isLocked
;
412 allocator().free(params
);
417 DbImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS
*cred
)
419 CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS params
;
420 params
.accessCredentials
= const_cast<CSSM_ACCESS_CREDENTIALS
*>(cred
);
421 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_CHANGE_PASSWORD
, ¶ms
, NULL
));
424 void DbImpl::recode(const CSSM_DATA
&data
, const CSSM_DATA
&extraData
)
426 // setup parameters for the recode call
427 CSSM_APPLECSPDL_RECODE_PARAMETERS params
;
428 params
.dbBlob
= data
;
429 params
.extraData
= extraData
;
432 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_CSP_RECODE
, ¶ms
, NULL
));
435 void DbImpl::copyBlob (CssmData
&data
)
438 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_COPY_BLOB
, NULL
, (void**) (CSSM_DATA
*) &data
));
441 void DbImpl::setBatchMode(Boolean mode
, Boolean rollback
)
444 // We need the DL_DB_Handle of the underyling DL in order to use CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT
447 CSSM_DL_DB_HANDLE dldbHandleOfUnderlyingDL
;
448 result
= CSSM_DL_PassThrough(handle(),
449 CSSM_APPLECSPDL_DB_GET_HANDLE
,
451 (void **)&dldbHandleOfUnderlyingDL
);
453 // Now, toggle the autocommit...
455 if ( result
== errSecSuccess
)
457 CSSM_BOOL modeToUse
= !mode
;
460 result
= (OSStatus
)CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL
,
461 CSSM_APPLEFILEDL_ROLLBACK
, NULL
, NULL
);
464 result
= CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL
,
465 CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT
,
466 (void *)((size_t) modeToUse
),
468 if (!rollback
&& modeToUse
)
469 result
= CSSM_DL_PassThrough(dldbHandleOfUnderlyingDL
,
470 CSSM_APPLEFILEDL_COMMIT
,
476 uint32
DbImpl::dbBlobVersion() {
477 uint32 dbBlobVersion
= 0;
478 uint32
* dbBlobVersionPtr
= &dbBlobVersion
;
480 // We only have a blob version if we're an apple CSPDL
481 if(dl()->guid() == gGuidAppleCSPDL
) {
482 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_BLOB_VERSION
, NULL
, (void**) &dbBlobVersionPtr
));
484 secnotice("integrity", "Non-Apple CSPDL keychains don't have keychain versions");
486 return dbBlobVersion
;
489 uint32
DbImpl::recodeDbToVersion(uint32 version
) {
491 uint32
* newDbVersionPtr
= &newDbVersion
;
492 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_TO_BLOB_VERSION
, &version
, (void**) &newDbVersionPtr
));
496 void DbImpl::recodeFinished() {
497 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_FINISHED
, NULL
, NULL
));
500 void DbImpl::takeFileLock() {
501 passThrough(CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK
, NULL
, NULL
);
504 void DbImpl::releaseFileLock(bool success
) {
505 passThrough(CSSM_APPLECSPDL_DB_RELEASE_FILE_LOCK
, &success
, NULL
);
508 void DbImpl::makeBackup() {
509 passThrough(CSSM_APPLECSPDL_DB_MAKE_BACKUP
, NULL
, NULL
);
512 void DbImpl::makeCopy(const char* path
) {
513 passThrough(CSSM_APPLECSPDL_DB_MAKE_COPY
, path
, NULL
);
516 void DbImpl::deleteFile() {
517 passThrough(CSSM_APPLECSPDL_DB_DELETE_FILE
, NULL
, NULL
);
520 void DbImpl::transferTo(const DLDbIdentifier
& dldbidentifier
) {
521 if (dldbidentifier
.ssuid().subserviceType() & CSSM_SERVICE_CSP
) {
522 // if we're an Apple CSPDL, do the fancy transfer:
523 // clone the file, clone the db, remove the original file
524 string oldPath
= name();
526 CSSM_DB_HANDLE dbhandle
;
527 passThrough(CSSM_APPLECSPDL_DB_CLONE
, &dldbidentifier
, &dbhandle
);
529 mDbName
= dldbidentifier
.dbName();
530 mHandle
.DBHandle
= dbhandle
;
532 unlink(oldPath
.c_str());
534 // Don't cache this name
535 if (mNameFromHandle
) {
536 allocator().free(mNameFromHandle
);
537 mNameFromHandle
= NULL
;
540 // if we're not an Apple CSPDL, just call rename
541 this->rename(dldbidentifier
.dbName());
546 // cloneTo only makes sense if you're on an Apple CSPDL
547 Db
DbImpl::cloneTo(const DLDbIdentifier
& dldbidentifier
) {
548 CSSM_DB_HANDLE dbhandle
;
549 passThrough(CSSM_APPLECSPDL_DB_CLONE
, &dldbidentifier
, &dbhandle
);
551 // This is the only reasonable way to make a SSDbImpl at this layer.
552 CssmClient::Db
db(dl(), dldbidentifier
.dbName(), dldbidentifier
.dbLocation());
553 db
->mHandle
.DBHandle
= dbhandle
;
562 DbImpl::newDbCursor(const CSSM_QUERY
&query
, Allocator
&allocator
)
564 return new DbDbCursorImpl(Db(this), query
, allocator
);
568 DbImpl::newDbCursor(uint32 capacity
, Allocator
&allocator
)
570 return new DbDbCursorImpl(Db(this), capacity
, allocator
);
575 // Db adapters for AclBearer
577 void DbImpl::getAcl(AutoAclEntryInfoList
&aclInfos
, const char *selectionTag
) const
579 aclInfos
.allocator(allocator());
580 check(CSSM_DL_GetDbAcl(const_cast<DbImpl
*>(this)->handle(),
581 reinterpret_cast<const CSSM_STRING
*>(selectionTag
), aclInfos
, aclInfos
));
584 void DbImpl::changeAcl(const CSSM_ACL_EDIT
&aclEdit
,
585 const CSSM_ACCESS_CREDENTIALS
*accessCred
)
587 check(CSSM_DL_ChangeDbAcl(handle(), AccessCredentials::needed(accessCred
), &aclEdit
));
590 void DbImpl::getOwner(AutoAclOwnerPrototype
&owner
) const
592 owner
.allocator(allocator());
593 check(CSSM_DL_GetDbOwner(const_cast<DbImpl
*>(this)->handle(), owner
));
596 void DbImpl::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE
&newOwner
,
597 const CSSM_ACCESS_CREDENTIALS
*accessCred
)
599 check(CSSM_DL_ChangeDbOwner(handle(),
600 AccessCredentials::needed(accessCred
), &newOwner
));
603 void DbImpl::defaultCredentials(DefaultCredentialsMaker
*maker
)
605 mDefaultCredentials
= maker
;
610 // Abstract DefaultCredentialsMakers
612 DbImpl::DefaultCredentialsMaker::~DefaultCredentialsMaker()
617 // Db adapters for DLAccess
619 CSSM_HANDLE
Db::dlGetFirst(const CSSM_QUERY
&query
, CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
,
620 CSSM_DATA
*data
, CSSM_DB_UNIQUE_RECORD
*&id
)
623 switch (CSSM_RETURN rc
= CSSM_DL_DataGetFirst(handle(), &query
, &result
, &attributes
, data
, &id
)) {
626 case CSSMERR_DL_ENDOFDATA
:
627 return CSSM_INVALID_HANDLE
;
629 CssmError::throwMe(rc
);
630 return CSSM_INVALID_HANDLE
; // placebo
634 bool Db::dlGetNext(CSSM_HANDLE query
, CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
,
635 CSSM_DATA
*data
, CSSM_DB_UNIQUE_RECORD
*&id
)
637 CSSM_RETURN rc
= CSSM_DL_DataGetNext(handle(), query
, &attributes
, data
, &id
);
641 case CSSMERR_DL_ENDOFDATA
:
644 CssmError::throwMe(rc
);
645 return false; // placebo
649 void Db::dlAbortQuery(CSSM_HANDLE query
)
651 CssmError::check(CSSM_DL_DataAbortQuery(handle(), query
));
654 void Db::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD
*id
)
656 CssmError::check(CSSM_DL_FreeUniqueRecord(handle(), id
));
659 void Db::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD
*id
)
661 CssmError::check(CSSM_DL_DataDelete(handle(), id
));
664 Allocator
&Db::allocator()
666 return Object::allocator();
671 // DbUniqueRecordMaker
674 DbImpl::newDbUniqueRecord()
676 return new DbUniqueRecordImpl(Db(this));
684 DbImpl::dlDbIdentifier()
686 // Always use the same dbName and dbLocation that were passed in during
688 return DLDbIdentifier(dl()->subserviceUid(), mDbName
.canonicalName(), dbLocation());
695 DbDbCursorImpl::DbDbCursorImpl(const Db
&db
, const CSSM_QUERY
&query
, Allocator
&allocator
)
696 : DbCursorImpl(db
, query
, allocator
), mResultsHandle(CSSM_INVALID_HANDLE
)
700 DbDbCursorImpl::DbDbCursorImpl(const Db
&db
, uint32 capacity
, Allocator
&allocator
)
701 : DbCursorImpl(db
, capacity
, allocator
), mResultsHandle(CSSM_INVALID_HANDLE
)
705 DbDbCursorImpl::~DbDbCursorImpl()
715 DbDbCursorImpl::next(DbAttributes
*attributes
, ::CssmDataContainer
*data
, DbUniqueRecord
&uniqueId
)
718 attributes
->deleteValues();
725 DbUniqueRecord
unique(db
);
728 // ask the CSP/DL if the requested record type exists
729 CSSM_BOOL boolResult
;
730 CSSM_DL_PassThrough(db
->handle(), CSSM_APPLECSPDL_DB_RELATION_EXISTS
, &RecordType
, (void**) &boolResult
);
741 result
= CSSM_DL_DataGetFirst(db
->handle(),
748 StLock
<Mutex
> _(mActivateMutex
);
749 if (result
== CSSM_OK
)
751 else if (data
!= NULL
)
756 result
= CSSM_DL_DataGetNext(db
->handle(),
762 if (result
!= CSSM_OK
&& data
!= NULL
)
768 if (result
!= CSSM_OK
&& attributes
!= NULL
)
770 attributes
->invalidate();
773 if (result
== CSSMERR_DL_ENDOFDATA
)
775 StLock
<Mutex
> _(mActivateMutex
);
782 // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope.
789 DbDbCursorImpl::activate()
794 DbDbCursorImpl::deactivate()
796 StLock
<Mutex
> _(mActivateMutex
);
800 check(CSSM_DL_DataAbortQuery(database()->handle(), mResultsHandle
));
808 DbCursorImpl::DbCursorImpl(const Object
&parent
, const CSSM_QUERY
&query
, Allocator
&allocator
) :
809 ObjectImpl(parent
), CssmAutoQuery(query
, allocator
)
813 DbCursorImpl::DbCursorImpl(const Object
&parent
, uint32 capacity
, Allocator
&allocator
) :
814 ObjectImpl(parent
), CssmAutoQuery(capacity
, allocator
)
819 DbCursorImpl::allocator() const
821 return ObjectImpl::allocator();
825 DbCursorImpl::allocator(Allocator
&alloc
)
827 ObjectImpl::allocator(alloc
);
834 DbUniqueRecordImpl::DbUniqueRecordImpl(const Db
&db
) : ObjectImpl(db
), mDestroyID (false)
838 DbUniqueRecordImpl::~DbUniqueRecordImpl()
844 allocator ().free (mUniqueId
);
853 DbUniqueRecordImpl::deleteRecord()
855 check(CSSM_DL_DataDelete(database()->handle(), mUniqueId
));
859 DbUniqueRecordImpl::modify(CSSM_DB_RECORDTYPE recordType
,
860 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
861 const CSSM_DATA
*data
,
862 CSSM_DB_MODIFY_MODE modifyMode
)
864 check(CSSM_DL_DataModify(database()->handle(), recordType
, mUniqueId
,
870 DbUniqueRecordImpl::modifyWithoutEncryption(CSSM_DB_RECORDTYPE recordType
,
871 const CSSM_DB_RECORD_ATTRIBUTE_DATA
*attributes
,
872 const CSSM_DATA
*data
,
873 CSSM_DB_MODIFY_MODE modifyMode
)
875 // fill out the parameters
876 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS params
;
877 params
.recordType
= recordType
;
878 params
.uniqueID
= mUniqueId
;
879 params
.attributes
= const_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA
*>(attributes
);
880 params
.data
= (CSSM_DATA
*) data
;
881 params
.modifyMode
= modifyMode
;
884 check(CSSM_DL_PassThrough(database()->handle(),
885 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION
,
891 DbUniqueRecordImpl::get(DbAttributes
*attributes
,
892 ::CssmDataContainer
*data
)
895 attributes
->deleteValues();
900 // @@@ Fix the allocators for attributes and data.
902 result
= CSSM_DL_DataGetFromUniqueRecordId(database()->handle(), mUniqueId
,
906 if (result
!= CSSM_OK
)
909 attributes
->invalidate();
910 if (data
!= NULL
) // the data returned is no longer valid
920 DbUniqueRecordImpl::getWithoutEncryption(DbAttributes
*attributes
,
921 ::CssmDataContainer
*data
)
924 attributes
->deleteValues();
929 // @@@ Fix the allocators for attributes and data.
932 // make the parameter block
933 CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS params
;
934 params
.uniqueID
= mUniqueId
;
935 params
.attributes
= attributes
;
938 ::CssmDataContainer recordData
;
939 result
= CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION
, ¶ms
,
945 DbUniqueRecordImpl::activate()
947 StLock
<Mutex
> _(mActivateMutex
);
952 DbUniqueRecordImpl::deactivate()
954 StLock
<Mutex
> _(mActivateMutex
);
958 check(CSSM_DL_FreeUniqueRecord(database()->handle(), mUniqueId
));
963 DbUniqueRecordImpl::getRecordIdentifier(CSSM_DATA
&data
)
965 check(CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER
,
966 mUniqueId
, (void**) &data
));
969 void DbUniqueRecordImpl::setUniqueRecordPtr(CSSM_DB_UNIQUE_RECORD_PTR uniquePtr
)
972 mUniqueId
= (CSSM_DB_UNIQUE_RECORD_PTR
) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD
));
973 *mUniqueId
= *uniquePtr
;
980 DbAttributes::DbAttributes()
981 : CssmAutoDbRecordAttributeData(0, Allocator::standard(), Allocator::standard())
985 DbAttributes::DbAttributes(const Db
&db
, uint32 capacity
, Allocator
&allocator
)
986 : CssmAutoDbRecordAttributeData(capacity
, db
->allocator(), allocator
)
990 void DbAttributes::updateWithDbAttributes(DbAttributes
* newValues
) {
996 newValues
->canonicalize();
998 updateWith(newValues
);
1002 DbAttributes::canonicalize() {
1003 for(int i
= 0; i
< size(); i
++) {
1004 CssmDbAttributeData
& data
= attributes()[i
];
1005 CssmDbAttributeInfo
& datainfo
= data
.info();
1007 // Calling Schema::attributeInfo is the best way to canonicalize.
1008 // There's no way around the try-catch structure, since it throws if it
1009 // can't find something.
1012 if(datainfo
.nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
) {
1013 data
.info() = Security::KeychainCore::Schema::attributeInfo(datainfo
.intName());
1016 // Don't worry about it