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 28using 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 33const uint32 kBlobType = 0x1; 34#pragma clang diagnostic pop 35 36// 37// Abstract classes 38// 39DbMaker::~DbMaker() 40{ /* virtual */ } 41 42DbCursorMaker::~DbCursorMaker() 43{ /* virtual */ } 44 45DbUniqueRecordMaker::~DbUniqueRecordMaker() 46{ /* virtual */ } 47 48 49// 50// Manage DL attachments 51// 52DLImpl::DLImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_DL) 53{ 54} 55 56DLImpl::DLImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_DL) 57{ 58} 59 60DLImpl::~DLImpl() 61{ 62} 63 64void 65DLImpl::getDbNames(char **) 66{ 67 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); 68} 69 70void 71DLImpl::freeNameList(char **) 72{ 73 CssmError::throwMe(CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); 74} 75 76DbImpl * 77DLImpl::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// 86DbImpl::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 95DbImpl::~DbImpl() 96{ 97 try 98 { 99 if (mNameFromHandle) 100 allocator().free(mNameFromHandle); 101 deactivate(); 102 } 103 catch(...) {} 104} 105 106void 107DbImpl::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 128void 129DbImpl::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, ¶ms, (void**) &mHandle.DBHandle)); 154} 155 156void 157DbImpl::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 183void 184DbImpl::close() 185{ 186 StLock<Mutex> _(mActivateMutex); 187 if (mActive) 188 { 189 check(CSSM_DL_DbClose (mHandle)); 190 mActive = false; 191 } 192} 193 194void 195DbImpl::activate() 196{ 197 if (!mActive) 198 { 199 if (mDbInfo) 200 create(); 201 else 202 open(); 203 } 204} 205 206void 207DbImpl::deactivate() 208{ 209 StLock<Mutex> _(mActivateMutex); 210 if (mActive) 211 { 212 mActive = false; 213 close(); 214 } 215} 216 217void 218DbImpl::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 227void 228DbImpl::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 239void 240DbImpl::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 260void 261DbImpl::name(char *&outDbName) 262{ 263 check(CSSM_DL_GetDbNameFromHandle(handle(), &outDbName)); 264} 265 266const char * 267DbImpl::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 285void 286DbImpl::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 298void 299DbImpl::destroyRelation(CSSM_DB_RECORDTYPE inRelationID) 300{ 301 check(CSSM_DL_DestroyRelation(handle(), inRelationID)); 302} 303 304DbUniqueRecord 305DbImpl::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 318DbUniqueRecord 319DbImpl::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, ¶ms, (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// 345void 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// 354void 355DbImpl::lock() 356{ 357 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_LOCK, NULL, NULL)); 358} 359 360void 361DbImpl::unlock() 362{ 363 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, NULL, NULL)); 364} 365 366void 367DbImpl::unlock(const CSSM_DATA &password) 368{ 369 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_UNLOCK, &password, NULL)); 370} 371 372void 373DbImpl::stash() 374{ 375 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_STASH, NULL, NULL)); 376} 377 378void 379DbImpl::stashCheck() 380{ 381 check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_STASH_CHECK, NULL, NULL)); 382} 383 384void 385DbImpl::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 395void 396DbImpl::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 404bool 405DbImpl::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 **>(¶ms))); 410 bool isLocked = params->isLocked; 411 allocator().free(params); 412 return isLocked; 413} 414 415void 416DbImpl::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, ¶ms, NULL)); 421} 422 423void 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, ¶ms, NULL)); 432} 433 434void 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 440void 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// 478DbCursorImpl * 479DbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) 480{ 481 return new DbDbCursorImpl(Db(this), query, allocator); 482} 483 484DbCursorImpl * 485DbImpl::newDbCursor(uint32 capacity, Allocator &allocator) 486{ 487 return new DbDbCursorImpl(Db(this), capacity, allocator); 488} 489 490 491// 492// Db adapters for AclBearer 493// 494void 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 501void 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 507void DbImpl::getOwner(AutoAclOwnerPrototype &owner) const 508{ 509 owner.allocator(allocator()); 510 check(CSSM_DL_GetDbOwner(const_cast<DbImpl*>(this)->handle(), owner)); 511} 512 513void 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 520void DbImpl::defaultCredentials(DefaultCredentialsMaker *maker) 521{ 522 mDefaultCredentials = maker; 523} 524 525 526// 527// Abstract DefaultCredentialsMakers 528// 529DbImpl::DefaultCredentialsMaker::~DefaultCredentialsMaker() 530{ /* virtual */ } 531 532 533// 534// Db adapters for DLAccess 535// 536CSSM_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 551bool 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 566void Db::dlAbortQuery(CSSM_HANDLE query) 567{ 568 CssmError::check(CSSM_DL_DataAbortQuery(handle(), query)); 569} 570 571void Db::dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id) 572{ 573 CssmError::check(CSSM_DL_FreeUniqueRecord(handle(), id)); 574} 575 576void Db::dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id) 577{ 578 CssmError::check(CSSM_DL_DataDelete(handle(), id)); 579} 580 581Allocator &Db::allocator() 582{ 583 return Object::allocator(); 584} 585 586 587// 588// DbUniqueRecordMaker 589// 590DbUniqueRecordImpl * 591DbImpl::newDbUniqueRecord() 592{ 593 return new DbUniqueRecordImpl(Db(this)); 594} 595 596 597// 598// Utility methods 599// 600DLDbIdentifier 601DbImpl::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// 612DbDbCursorImpl::DbDbCursorImpl(const Db &db, const CSSM_QUERY &query, Allocator &allocator) 613: DbCursorImpl(db, query, allocator), mResultsHandle(CSSM_INVALID_HANDLE) 614{ 615} 616 617DbDbCursorImpl::DbDbCursorImpl(const Db &db, uint32 capacity, Allocator &allocator) 618: DbCursorImpl(db, capacity, allocator), mResultsHandle(CSSM_INVALID_HANDLE) 619{ 620} 621 622DbDbCursorImpl::~DbDbCursorImpl() 623{ 624 try 625 { 626 deactivate(); 627 } 628 catch(...) {} 629} 630 631bool 632DbDbCursorImpl::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 705void 706DbDbCursorImpl::activate() 707{ 708} 709 710void 711DbDbCursorImpl::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// 725DbCursorImpl::DbCursorImpl(const Object &parent, const CSSM_QUERY &query, Allocator &allocator) : 726ObjectImpl(parent), CssmAutoQuery(query, allocator) 727{ 728} 729 730DbCursorImpl::DbCursorImpl(const Object &parent, uint32 capacity, Allocator &allocator) : 731ObjectImpl(parent), CssmAutoQuery(capacity, allocator) 732{ 733} 734 735Allocator & 736DbCursorImpl::allocator() const 737{ 738 return ObjectImpl::allocator(); 739} 740 741void 742DbCursorImpl::allocator(Allocator &alloc) 743{ 744 ObjectImpl::allocator(alloc); 745} 746 747 748// 749// DbUniqueRecord 750// 751DbUniqueRecordImpl::DbUniqueRecordImpl(const Db &db) : ObjectImpl(db), mDestroyID (false) 752{ 753} 754 755DbUniqueRecordImpl::~DbUniqueRecordImpl() 756{ 757 try 758 { 759 if (mDestroyID) 760 { 761 allocator ().free (mUniqueId); 762 } 763 764 deactivate(); 765 } 766 catch(...) {} 767} 768 769void 770DbUniqueRecordImpl::deleteRecord() 771{ 772 check(CSSM_DL_DataDelete(database()->handle(), mUniqueId)); 773} 774 775void 776DbUniqueRecordImpl::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 786void 787DbUniqueRecordImpl::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 ¶ms, 804 NULL)); 805} 806 807void 808DbUniqueRecordImpl::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 836void 837DbUniqueRecordImpl::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, ¶ms, 857 (void**) data); 858 check (result); 859} 860 861void 862DbUniqueRecordImpl::activate() 863{ 864 StLock<Mutex> _(mActivateMutex); 865 mActive = true; 866} 867 868void 869DbUniqueRecordImpl::deactivate() 870{ 871 StLock<Mutex> _(mActivateMutex); 872 if (mActive) 873 { 874 mActive = false; 875 check(CSSM_DL_FreeUniqueRecord(database()->handle(), mUniqueId)); 876 } 877} 878 879void 880DbUniqueRecordImpl::getRecordIdentifier(CSSM_DATA &data) 881{ 882 check(CSSM_DL_PassThrough(database()->handle(), CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER, 883 mUniqueId, (void**) &data)); 884} 885 886void 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// 897DbAttributes::DbAttributes() 898: CssmAutoDbRecordAttributeData(0, Allocator::standard(), Allocator::standard()) 899{ 900} 901 902DbAttributes::DbAttributes(const Db &db, uint32 capacity, Allocator &allocator) 903: CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator) 904{ 905} 906