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