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// SSDLSession.h - DL session for security server CSP/DL. 21// 22#include "SSDLSession.h" 23 24#include "CSPDLPlugin.h" 25#include "SSKey.h" 26#include <security_cdsa_utilities/cssmbridge.h> 27#include <Security/cssmapplePriv.h> 28 29using namespace CssmClient; 30using namespace SecurityServer; 31using namespace std; 32 33// 34// SSDLSession -- Security Server DL session 35// 36SSDLSession::SSDLSession(CSSM_MODULE_HANDLE handle, 37 CSPDLPlugin &plug, 38 const CSSM_VERSION &version, 39 uint32 subserviceId, 40 CSSM_SERVICE_TYPE subserviceType, 41 CSSM_ATTACH_FLAGS attachFlags, 42 const CSSM_UPCALLS &upcalls, 43 DatabaseManager &databaseManager, 44 SSCSPDLSession &ssCSPDLSession) 45: DLPluginSession(handle, plug, version, subserviceId, subserviceType, 46 attachFlags, upcalls, databaseManager), 47 mSSCSPDLSession(ssCSPDLSession), 48 mDL(Module(gGuidAppleFileDL, Cssm::standard())), 49 mClientSession(Allocator::standard(), static_cast<PluginSession &>(*this)) 50{ 51 mClientSession.registerForAclEdits(SSCSPDLSession::didChangeKeyAclCallback, &mSSCSPDLSession); 52 // @@@ mDL.allocator(*static_cast<DatabaseSession *>(this)); 53 mDL->allocator(allocator()); 54 mDL->version(version); 55 mDL->subserviceId(subserviceId); 56 mDL->flags(attachFlags); 57 // fprintf(stderr, "%p: Created %p\n", pthread_self(), this); 58} 59 60SSDLSession::~SSDLSession() 61try 62{ 63 StLock<Mutex> _1(mSSUniqueRecordLock); 64 mSSUniqueRecordMap.clear(); 65 66 StLock<Mutex> _2(mDbHandleLock); 67 DbHandleMap::iterator end = mDbHandleMap.end(); 68 for (DbHandleMap::iterator it = mDbHandleMap.begin(); it != end; ++it) 69 it->second->close(); 70 71 mDbHandleMap.clear(); 72 mDL->detach(); 73} 74catch (...) 75{ 76} 77 78// Utility functions 79void 80SSDLSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList) 81{ 82 // @@@ Fix client lib 83 CSSM_DL_GetDbNames(mDL->handle(), &outNameList); 84} 85 86 87void 88SSDLSession::FreeNameList(CSSM_NAME_LIST &inNameList) 89{ 90 // @@@ Fix client lib 91 CSSM_DL_FreeNameList(mDL->handle(), &inNameList); 92} 93 94 95void 96SSDLSession::DbDelete(const char *inDbName, 97 const CSSM_NET_ADDRESS *inDbLocation, 98 const AccessCredentials *inAccessCred) 99{ 100 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); 101 db->accessCredentials(inAccessCred); 102 db->deleteDb(); 103} 104 105// DbContext creation and destruction. 106void 107SSDLSession::DbCreate(const char *inDbName, 108 const CSSM_NET_ADDRESS *inDbLocation, 109 const CSSM_DBINFO &inDBInfo, 110 CSSM_DB_ACCESS_TYPE inAccessRequest, 111 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, 112 const void *inOpenParameters, 113 CSSM_DB_HANDLE &outDbHandle) 114{ 115 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); 116 db->dbInfo(&inDBInfo); 117 db->accessRequest(inAccessRequest); 118 db->resourceControlContext(inCredAndAclEntry); 119 db->openParameters(inOpenParameters); 120 db->create(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), 121 CSSM_SERVICE_DL | CSSM_SERVICE_CSP), 122 inDbName, inDbLocation)); 123 db->dbInfo(NULL); 124 outDbHandle = makeDbHandle(db); 125 // fprintf(stderr, "%p %p was created for %s in session %p\n", pthread_self(), (void*) outDbHandle, inDbName, this); 126} 127 128void 129SSDLSession::CreateWithBlob(const char *DbName, 130 const CSSM_NET_ADDRESS *DbLocation, 131 const CSSM_DBINFO &DBInfo, 132 CSSM_DB_ACCESS_TYPE AccessRequest, 133 const void *OpenParameters, 134 const CSSM_DATA &blob, 135 CSSM_DB_HANDLE &DbHandle) 136{ 137 SSDatabase db(mClientSession, mDL, DbName, DbLocation); 138 db->dbInfo(&DBInfo); 139 db->accessRequest(AccessRequest); 140 db->resourceControlContext(NULL); 141 db->openParameters(OpenParameters); 142 db->createWithBlob(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), 143 CSSM_SERVICE_DL | CSSM_SERVICE_CSP), 144 DbName, DbLocation), 145 blob); 146 db->dbInfo(NULL); 147 DbHandle = makeDbHandle(db); 148 // fprintf(stderr, "%p %p was created with a blob in session %p\n", pthread_self(), (void*) DbHandle, this); 149} 150 151void 152SSDLSession::DbOpen(const char *inDbName, 153 const CSSM_NET_ADDRESS *inDbLocation, 154 CSSM_DB_ACCESS_TYPE inAccessRequest, 155 const AccessCredentials *inAccessCred, 156 const void *inOpenParameters, 157 CSSM_DB_HANDLE &outDbHandle) 158{ 159 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation); 160 db->accessRequest(inAccessRequest); 161 db->accessCredentials(inAccessCred); 162 db->openParameters(inOpenParameters); 163 db->open(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), 164 CSSM_SERVICE_DL | CSSM_SERVICE_CSP), 165 inDbName, inDbLocation)); 166 outDbHandle = makeDbHandle(db); 167 // fprintf(stderr, "%p %p was opened for %s in session %p\n", pthread_self(), (void*) outDbHandle, inDbName, this); 168} 169 170// Operations using DbContext instances. 171void 172SSDLSession::DbClose(CSSM_DB_HANDLE inDbHandle) 173{ 174 killDbHandle(inDbHandle)->close(); 175} 176 177void 178SSDLSession::CreateRelation(CSSM_DB_HANDLE inDbHandle, 179 CSSM_DB_RECORDTYPE inRelationID, 180 const char *inRelationName, 181 uint32 inNumberOfAttributes, 182 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, 183 uint32 inNumberOfIndexes, 184 const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) 185{ 186 SSDatabase db = findDbHandle(inDbHandle); 187 // @@@ Fix inAttributeInfo and inIndexInfo arguments (might be NULL if NumberOf = 0) 188 db->createRelation(inRelationID, inRelationName, 189 inNumberOfAttributes, inAttributeInfo, 190 inNumberOfIndexes, &inIndexInfo); 191} 192 193void 194SSDLSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle, 195 CSSM_DB_RECORDTYPE inRelationID) 196{ 197 // @@@ Check credentials. 198 SSDatabase db = findDbHandle(inDbHandle); 199 db->destroyRelation(inRelationID); 200} 201 202void 203SSDLSession::Authenticate(CSSM_DB_HANDLE inDbHandle, 204 CSSM_DB_ACCESS_TYPE inAccessRequest, 205 const AccessCredentials &inAccessCred) 206{ 207 SSDatabase db = findDbHandle(inDbHandle); 208 db->authenticate(inAccessRequest, &inAccessCred); 209} 210 211 212void 213SSDLSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle, 214 const CSSM_STRING *inSelectionTag, 215 uint32 &outNumberOfAclInfos, 216 CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) 217{ 218 SSDatabase db = findDbHandle(inDbHandle); 219 mClientSession.getDbAcl(db->dbHandle(), 220 inSelectionTag ? *inSelectionTag : NULL, 221 outNumberOfAclInfos, AclEntryInfo::overlayVar(outAclInfos), allocator()); 222} 223 224void 225SSDLSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle, 226 const AccessCredentials &inAccessCred, 227 const CSSM_ACL_EDIT &inAclEdit) 228{ 229 SSDatabase db = findDbHandle(inDbHandle); 230 mClientSession.changeDbAcl(db->dbHandle(), inAccessCred, AclEdit::overlay(inAclEdit)); 231} 232 233void 234SSDLSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle, 235 CSSM_ACL_OWNER_PROTOTYPE &outOwner) 236{ 237 SSDatabase db = findDbHandle(inDbHandle); 238 mClientSession.getDbOwner(db->dbHandle(), 239 AclOwnerPrototype::overlay(outOwner), allocator()); 240} 241 242void 243SSDLSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle, 244 const AccessCredentials &inAccessCred, 245 const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) 246{ 247 SSDatabase db = findDbHandle(inDbHandle); 248 mClientSession.changeDbOwner(db->dbHandle(), inAccessCred, 249 AclOwnerPrototype::overlay(inNewOwner)); 250} 251 252void 253SSDLSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle, 254 char **outDbName) 255{ 256 SSDatabase db = findDbHandle(inDbHandle); 257 // @@@ Fix this functions signature. 258 db->name(*outDbName); 259} 260 261void 262SSDLSession::DataInsert(CSSM_DB_HANDLE inDbHandle, 263 CSSM_DB_RECORDTYPE inRecordType, 264 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes, 265 const CssmData *inData, 266 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) 267{ 268 SSDatabase db = findDbHandle(inDbHandle); 269 // @@@ Fix client lib. 270 SSUniqueRecord uniqueId = db->insert(inRecordType, inAttributes, inData, true); // @@@ Fix me 271 outUniqueId = makeSSUniqueRecord(uniqueId); 272 // @@@ If this is a key do the right thing. 273} 274 275void 276SSDLSession::DataDelete(CSSM_DB_HANDLE inDbHandle, 277 const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) 278{ 279 SSDatabase db = findDbHandle(inDbHandle); 280 SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecordIdentifier); 281 uniqueId->deleteRecord(); 282 // @@@ If this is a key do the right thing. 283} 284 285 286void 287SSDLSession::DataModify(CSSM_DB_HANDLE inDbHandle, 288 CSSM_DB_RECORDTYPE inRecordType, 289 CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier, 290 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified, 291 const CssmData *inDataToBeModified, 292 CSSM_DB_MODIFY_MODE inModifyMode) 293{ 294 SSDatabase db = findDbHandle(inDbHandle); 295 SSUniqueRecord uniqueId = findSSUniqueRecord(inoutUniqueRecordIdentifier); 296 uniqueId->modify(inRecordType, inAttributesToBeModified, inDataToBeModified, inModifyMode); 297 // @@@ If this is a key do the right thing. 298} 299 300CSSM_HANDLE 301SSDLSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle, 302 const CssmQuery *inQuery, 303 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, 304 CssmData *inoutData, 305 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) 306{ 307 SSDatabase db = findDbHandle(inDbHandle); 308 CSSM_HANDLE resultsHandle = CSSM_INVALID_HANDLE; 309 SSUniqueRecord uniqueId(db); 310 311 // Setup so we always retrive the attributes even if the client 312 // doesn't want them so we can figure out if we just retrived a key. 313 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes; 314 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; 315 if (inoutAttributes) 316 pAttributes = inoutAttributes; 317 else 318 { 319 pAttributes = &attributes; 320 memset(pAttributes, 0, sizeof(attributes)); 321 } 322 323 // Retrive the record. 324 CSSM_RETURN result = CSSM_DL_DataGetFirst(db->handle(), inQuery, &resultsHandle, 325 pAttributes, inoutData, uniqueId); 326 if (result) 327 { 328 if (result == CSSMERR_DL_ENDOFDATA) 329 return CSSM_INVALID_HANDLE; 330 331 CssmError::throwMe(result); 332 } 333 334 uniqueId->activate(); 335 336 // If we the client didn't ask for data then it doesn't matter 337 // if this record is a key or not, just return it. 338 if (inoutData) 339 { 340 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY 341 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY 342 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) 343 { 344 // This record is a key, do the right thing (tm). 345 // Allocate storage for the key. 346 CssmKey *outKey = DatabaseSession::alloc<CssmKey>(); 347 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); 348 349 // Free the data we retrived (keyblob) 350 allocator().free(inoutData->Data); 351 352 // Set the length and data on the data we return to the client 353 inoutData->Length = sizeof(*outKey); 354 inoutData->Data = reinterpret_cast<uint8 *>(outKey); 355 } 356 } 357 358 outUniqueRecord = makeSSUniqueRecord(uniqueId); 359 return resultsHandle; 360} 361 362bool 363SSDLSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, 364 CSSM_HANDLE inResultsHandle, 365 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, 366 CssmData *inoutData, 367 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) 368{ 369 // @@@ If this is a key do the right thing. 370 SSDatabase db = findDbHandle(inDbHandle); 371 SSUniqueRecord uniqueId(db); 372 373 // Setup so we always retrive the attributes even if the client 374 // doesn't want them so we can figure out if we just retrived a key. 375 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes; 376 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; 377 if (inoutAttributes) 378 pAttributes = inoutAttributes; 379 else 380 { 381 pAttributes = &attributes; 382 memset(pAttributes, 0, sizeof(attributes)); 383 } 384 385 CSSM_RETURN result = CSSM_DL_DataGetNext(db->handle(), inResultsHandle, 386 inoutAttributes, inoutData, uniqueId); 387 if (result) 388 { 389 if (result == CSSMERR_DL_ENDOFDATA) 390 return false; 391 392 CssmError::throwMe(result); 393 } 394 395 uniqueId->activate(); 396 397 // If we the client didn't ask for data then it doesn't matter 398 // if this record is a key or not, just return it. 399 if (inoutData) 400 { 401 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY 402 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY 403 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) 404 { 405 // This record is a key, do the right thing (tm). 406 // Allocate storage for the key. 407 CssmKey *outKey = DatabaseSession::alloc<CssmKey>(); 408 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); 409 410 // Free the data we retrived (keyblob) 411 allocator().free(inoutData->Data); 412 413 // Set the length and data on the data we return to the client 414 inoutData->Length = sizeof(*outKey); 415 inoutData->Data = reinterpret_cast<uint8 *>(outKey); 416 } 417 } 418 419 outUniqueRecord = makeSSUniqueRecord(uniqueId); 420 421 return true; 422} 423 424void 425SSDLSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle, 426 CSSM_HANDLE inResultsHandle) 427{ 428 // @@@ If this is a key do the right thing. 429 SSDatabase db = findDbHandle(inDbHandle); 430 CSSM_RETURN result = CSSM_DL_DataAbortQuery(db->handle(), inResultsHandle); 431 if (result) 432 CssmError::throwMe(result); 433} 434 435void 436SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, 437 const CSSM_DB_UNIQUE_RECORD &inUniqueRecord, 438 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, 439 CssmData *inoutData) 440{ 441 SSDatabase db = findDbHandle(inDbHandle); 442 const SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecord); 443 444 // Setup so we always retrive the attributes even if the client 445 // doesn't want them so we can figure out if we just retrived a key. 446 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes; 447 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes; 448 if (inoutAttributes) 449 pAttributes = inoutAttributes; 450 else 451 { 452 pAttributes = &attributes; 453 memset(pAttributes, 0, sizeof(attributes)); 454 } 455 456 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), 457 uniqueId, pAttributes, inoutData); 458 if (result) 459 CssmError::throwMe(result); 460 461 if (inoutData) 462 { 463 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY 464 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY 465 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) 466 { 467 // This record is a key, do the right thing (tm). 468 // Allocate storage for the key. 469 CssmKey *outKey = DatabaseSession::alloc<CssmKey>(); 470 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData); 471 472 // Free the data we retrived (keyblob) 473 allocator().free(inoutData->Data); 474 475 // Set the length and data on the data we return to the client 476 inoutData->Length = sizeof(*outKey); 477 inoutData->Data = reinterpret_cast<uint8 *>(outKey); 478 } 479 } 480} 481 482void 483SSDLSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle, 484 CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) 485{ 486 killSSUniqueRecord(inUniqueRecordIdentifier); 487} 488 489#pragma clang diagnostic push 490#pragma clang diagnostic ignored "-Wunused-const-variable" 491 492static const uint32 kGenericAttributeNames[] = 493{ 494 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce', 495 'gena' 496}; 497 498const uint32 kNumGenericAttributes = sizeof (kGenericAttributeNames) / sizeof (uint32); 499 500static const uint32 kApplesharePasswordNames[] = 501{ 502 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'vlme', 503 'srvr', 'ptcl', 'addr', 'ssig' 504}; 505 506const uint32 kNumApplesharePasswordAttributes = sizeof (kApplesharePasswordNames) / sizeof (uint32); 507 508static const uint32 kInternetPasswordNames[] = 509{ 510 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'sdmn', 511 'srvr', 'ptcl', 'atyp', 'port', 'path' 512}; 513 514const uint32 kNumInternetPasswordAttributes = sizeof (kInternetPasswordNames) / sizeof (uint32); 515 516const uint32 kKeyAttributeNames[] = 517{ 518 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 519}; 520 521const uint32 kNumKeyAttributes = sizeof (kKeyAttributeNames) / sizeof (uint32); 522 523const uint32 kCertificateAttributeNames[] = 524{ 525 'ctyp', 'cenc', 'labl', 'alis', 'subj', 'issu', 'snbr', 'skid', 'hpky' 526}; 527 528const uint32 kNumCertificateAttributes = sizeof (kCertificateAttributeNames) / sizeof (uint32); 529 530const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key 531const unsigned kLabelSize = 20; 532const unsigned kNumSymmetricAttributes = 27; // number of attributes to request 533 534#pragma clang diagnostic pop 535 536static void appendUInt32ToData (const uint32 value, CssmDataContainer &data) 537{ 538 data.append (CssmPolyData (uint32 (htonl (value)))); 539} 540 541static inline uint32 GetUInt32AtFinger (uint8 *&finger) 542{ 543 uint32 a = ((finger[0] << 24) | (finger[1] << 16) | (finger[2] << 8) | finger[3]); 544 finger += sizeof (uint32); 545 return a; 546} 547 548void 549SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, 550 CSSM_DB_ATTRIBUTE_DATA_PTR &attributes, 551 CSSM_DATA &data, 552 CSSM_DATA &input) 553{ 554 // get the number of attributes 555 uint8* finger = input.Data; 556 numAttributes = GetUInt32AtFinger (finger); 557 558 // compute the end of the data for sanity checking later 559 uint8* maximum = input.Data + input.Length; 560 561 // make the attribute array 562 attributes = (CSSM_DB_ATTRIBUTE_DATA*) allocator ().malloc (numAttributes * sizeof (CSSM_DB_ATTRIBUTE_DATA)); 563 564 // for each attribute, retrieve the name format, name, type, and number of values 565 unsigned i; 566 for (i = 0; i < numAttributes; ++i) 567 { 568 attributes[i].Info.AttributeNameFormat = GetUInt32AtFinger (finger); 569 attributes[i].Info.Label.AttributeID = GetUInt32AtFinger (finger); 570 attributes[i].Info.AttributeFormat = GetUInt32AtFinger (finger); 571 attributes[i].NumberOfValues = GetUInt32AtFinger (finger); 572 573 // for each value, get the length and data 574 attributes[i].Value = (CSSM_DATA*) allocator ().malloc (sizeof (CSSM_DATA) * attributes[i].NumberOfValues); 575 unsigned j; 576 for (j = 0; j < attributes[i].NumberOfValues; ++j) 577 { 578 attributes[i].Value[j].Length = GetUInt32AtFinger (finger); 579 if (attributes[i].Value[j].Length != 0) 580 { 581 // sanity check what we are about to do 582 if (finger > maximum || finger + attributes[i].Value[j].Length > maximum) 583 { 584 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); 585 } 586 587 attributes[i].Value[j].Data = (uint8*) allocator ().malloc (attributes[i].Value[j].Length); 588 589 switch (attributes[i].Info.AttributeFormat) 590 { 591 default: 592 { 593 memmove (attributes[i].Value[j].Data, finger, attributes[i].Value[j].Length); 594 finger += attributes[i].Value[j].Length; 595 break; 596 } 597 598 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: 599 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: 600 { 601 *(uint32*) attributes[i].Value[j].Data = GetUInt32AtFinger (finger); 602 break; 603 } 604 605 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: 606 { 607 uint32* d = (uint32*) attributes[i].Value[j].Data; 608 unsigned long numValues = attributes[i].Value[j].Length / sizeof (UInt32); 609 while (numValues--) 610 { 611 *d++ = GetUInt32AtFinger (finger); 612 } 613 break; 614 } 615 } 616 } 617 else 618 { 619 attributes[i].Value[j].Data = NULL; 620 } 621 } 622 } 623 624 // get the data 625 data.Length = GetUInt32AtFinger (finger); 626 if (data.Length != 0) 627 { 628 // sanity check the pointer 629 if (finger + data.Length > maximum) 630 { 631 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); 632 } 633 634 data.Data = (uint8*) allocator ().malloc (data.Length); 635 memmove (data.Data, finger, data.Length); 636 finger += data.Length; 637 } 638 else 639 { 640 data.Data = NULL; 641 } 642} 643 644void 645SSDLSession::getWrappedAttributesAndData (SSDatabase &db, 646 CSSM_DB_RECORDTYPE recordType, 647 CSSM_DB_UNIQUE_RECORD_PTR recordPtr, 648 CssmDataContainer &output, 649 CSSM_DATA *dataBlob) 650{ 651 // figure out which attributes to use 652 const uint32* attributeNameArray; 653 uint32 numAttributeNames; 654 655 switch (recordType) 656 { 657 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: 658 { 659 attributeNameArray = kGenericAttributeNames; 660 numAttributeNames = kNumGenericAttributes; 661 break; 662 } 663 664 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: 665 { 666 attributeNameArray = kInternetPasswordNames; 667 numAttributeNames = kNumInternetPasswordAttributes; 668 break; 669 } 670 671 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: 672 { 673 attributeNameArray = kApplesharePasswordNames; 674 numAttributeNames = kNumApplesharePasswordAttributes; 675 break; 676 } 677 678 case CSSM_DL_DB_RECORD_X509_CERTIFICATE: 679 { 680 attributeNameArray = kCertificateAttributeNames; 681 numAttributeNames = kNumCertificateAttributes; 682 break; 683 } 684 685 case CSSM_DL_DB_RECORD_PUBLIC_KEY: 686 case CSSM_DL_DB_RECORD_PRIVATE_KEY: 687 case CSSM_DL_DB_RECORD_SYMMETRIC_KEY: 688 { 689 attributeNameArray = kKeyAttributeNames; 690 numAttributeNames = kNumKeyAttributes; 691 break; 692 } 693 694 default: 695 { 696 CssmError::throwMe (CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); 697 } 698 } 699 700 // make the attribute array 701 size_t arraySize = numAttributeNames * sizeof (CSSM_DB_ATTRIBUTE_DATA); 702 703 CSSM_DB_ATTRIBUTE_DATA_PTR attributes = 704 (CSSM_DB_ATTRIBUTE_DATA_PTR) allocator ().malloc (arraySize); 705 706 // initialize the array 707 memset (attributes, 0, arraySize); 708 unsigned i; 709 for (i = 0; i < numAttributeNames; ++i) 710 { 711 attributes[i].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; 712 attributes[i].Info.Label.AttributeID = attributeNameArray[i]; 713 } 714 715 // make the attribute record 716 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; 717 attrData.DataRecordType = recordType; 718 attrData.SemanticInformation = 0; 719 attrData.NumberOfAttributes = numAttributeNames; 720 attrData.AttributeData = attributes; 721 722 // get the data 723 CssmDataContainer data; 724 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId (db->handle (), 725 recordPtr, 726 &attrData, 727 &data); 728 if (result != 0) 729 { 730 CssmError::throwMe (result); 731 } 732 733 // wrap the data -- write the number of attributes 734 appendUInt32ToData (numAttributeNames, output); 735 736 // for each attribute, write the type and number of values 737 for (i = 0; i < numAttributeNames; ++i) 738 { 739 appendUInt32ToData (attributes[i].Info.AttributeNameFormat, output); 740 appendUInt32ToData (attributes[i].Info.Label.AttributeID, output); 741 appendUInt32ToData (attributes[i].Info.AttributeFormat, output); 742 appendUInt32ToData (attributes[i].NumberOfValues, output); 743 744 // for each value, write the name format, name, length and the data 745 unsigned j; 746 for (j = 0; j < attributes[i].NumberOfValues; ++j) 747 { 748 appendUInt32ToData ((uint32)attributes[i].Value[j].Length, output); 749 if (attributes[i].Value[j].Length != 0) 750 { 751 switch (attributes[i].Info.AttributeFormat) 752 { 753 default: 754 { 755 output.append (CssmPolyData (attributes[i].Value[j])); 756 break; 757 } 758 759 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: 760 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: 761 { 762 uint32 n = htonl (*(uint32*) attributes[i].Value[j].Data); 763 CSSM_DATA d; 764 d.Length = sizeof (uint32); 765 d.Data = (uint8*) &n; 766 output.append (CssmPolyData (d)); 767 break; 768 } 769 } 770 } 771 } 772 } 773 774 // write the length of the data 775 appendUInt32ToData ((uint32)data.Length, output); 776 777 // write the data itself 778 if (data.Length != 0) 779 { 780 output.append (CssmPolyData (data)); 781 } 782 783 // clean up 784 for (i = 0; i < numAttributeNames; ++i) 785 { 786 unsigned j; 787 for (j = 0; j < attributes[i].NumberOfValues; ++j) 788 { 789 allocator ().free (attributes[i].Value[j].Data); 790 } 791 792 allocator ().free (attributes[i].Value); 793 } 794 795 allocator ().free (attributes); 796 797 // copy out the data if the caller needs it 798 if (dataBlob) 799 { 800 dataBlob->Data = data.Data; 801 dataBlob->Length = data.Length; 802 data.Data = NULL; 803 data.Length = 0; 804 } 805} 806 807void 808SSDLSession::getUniqueIdForSymmetricKey (SSDatabase &db, CSSM_DATA &label, 809 CSSM_DB_UNIQUE_RECORD_PTR &uniqueRecord) 810{ 811 // set up a query to get the key 812 CSSM_SELECTION_PREDICATE predicate; 813 predicate.DbOperator = CSSM_DB_EQUAL; 814 predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; 815 predicate.Attribute.Info.Label.AttributeID = kSymmetricKeyLabel; 816 predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; 817 predicate.Attribute.NumberOfValues = 1; 818 // the label of the corresponding key is the first 20 bytes of the blob we returned 819 predicate.Attribute.Value = &label; 820 821 CSSM_QUERY query; 822 query.RecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; 823 query.Conjunctive = CSSM_DB_NONE; 824 query.NumSelectionPredicates = 1; 825 query.SelectionPredicate = &predicate; 826 827 // fill out the record data 828 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttributeData; 829 recordAttributeData.DataRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; 830 recordAttributeData.SemanticInformation = 0; 831 recordAttributeData.NumberOfAttributes = 0; 832 recordAttributeData.AttributeData = NULL; 833 834 // get the data 835 CSSM_HANDLE handle; 836 CSSM_RETURN result = CSSM_DL_DataGetFirst (db->handle (), &query, &handle, &recordAttributeData, NULL, 837 &uniqueRecord); 838 if (result) 839 { 840 CssmError::throwMe (result); 841 } 842 843 // clean up 844 CSSM_DL_DataAbortQuery (db->handle (), handle); 845} 846 847void 848SSDLSession::getCorrespondingSymmetricKey (SSDatabase &db, CSSM_DATA &labelData, CssmDataContainer &data) 849{ 850 // get the unique ID 851 CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord; 852 getUniqueIdForSymmetricKey (db, labelData, uniqueRecord); 853 854 // from this. get the wrapped attributes and data 855 getWrappedAttributesAndData (db, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueRecord, data, NULL); 856 857 // clean up after the query 858 CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord); 859} 860 861void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputParams, void **outOutputParams) 862{ 863 CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS* params = 864 (CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; 865 866 SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID)); 867 868 CSSM_DATA *outputData = (CSSM_DATA*) outOutputParams; 869 CssmDataContainer output; 870 871 // get the record type and requested attributes from the DL 872 CssmDataContainer data; 873 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), 874 uniqueID, 875 params->attributes, 876 NULL); 877 878 if (result) 879 { 880 CssmError::throwMe(result); 881 } 882 883 // get the real data and all of the attributes from the DL 884 CssmDataContainer blobData; 885 getWrappedAttributesAndData (db, params->attributes->DataRecordType, uniqueID, data, &blobData); 886 887 // write out the data blob 888 appendUInt32ToData ((uint32)data.Length, output); 889 output.append (CssmPolyData (data)); 890 891 // figure out what we need to do with the key blob 892 CssmDataContainer key; 893 switch (params->attributes->DataRecordType) 894 { 895 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: 896 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: 897 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: 898 { 899 // the label is the first kLabelSize bytes of the resultant data blob 900 CSSM_DATA label = {kLabelSize, blobData.Data}; 901 902 // get the key 903 getCorrespondingSymmetricKey (db, label, key); 904 } 905 break; 906 907 default: 908 { 909 break; 910 } 911 } 912 913 914 // write out the length of the key blob 915 appendUInt32ToData ((uint32)key.Length, output); 916 917 if (key.Length != 0) 918 { 919 // write the key 920 output.append (CssmPolyData (key)); 921 } 922 923 // copy out the results 924 outputData->Data = output.Data; 925 output.Data = NULL; 926 outputData->Length = output.Length; 927 output.Length = 0; 928} 929 930void 931SSDLSession::cleanupAttributes (uint32 numAttributes, CSSM_DB_ATTRIBUTE_DATA_PTR attributes) 932{ 933 unsigned i; 934 for (i = 0; i < numAttributes; ++i) 935 { 936 unsigned j; 937 for (j = 0; j < attributes[i].NumberOfValues; ++j) 938 { 939 free (attributes[i].Value[j].Data); 940 } 941 942 free (attributes[i].Value); 943 } 944 945 free (attributes); 946} 947 948void 949SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams) 950{ 951 CSSM_RETURN result; 952 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS* params = 953 (CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; 954 955 // extract the data for this modify. 956 uint8* finger = params->data->Data; 957 CSSM_DATA data; 958 data.Length = GetUInt32AtFinger (finger); 959 data.Data = finger; 960 if (data.Length + sizeof (UInt32) > params->data->Length) 961 { 962 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); 963 } 964 965 // point to the key 966 finger += data.Length; 967 968 // reconstruct the attributes and data 969 uint32 numAttributes; 970 CSSM_DB_ATTRIBUTE_DATA_PTR attributes; 971 CssmDataContainer dataBlob; 972 973 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); 974 975 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; 976 attrData.DataRecordType = params->attributes->DataRecordType; 977 attrData.SemanticInformation = 0; 978 attrData.NumberOfAttributes = numAttributes; 979 attrData.AttributeData = attributes; 980 981 // get the unique ID for this record (from the db's perspective) 982 SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID)); 983 CSSM_DB_UNIQUE_RECORD *uniqueIDPtr = uniqueID; // for readability. There's cast overloading 984 // going on here. 985 986 switch (attrData.DataRecordType) 987 { 988 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: 989 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: 990 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: 991 { 992 // read off the data so that we can update the key 993 CssmDataContainer oldData; 994 result = CSSM_DL_DataGetFromUniqueRecordId (db->handle(), 995 uniqueIDPtr, 996 NULL, 997 &oldData); 998 if (result) 999 { 1000 CssmError::throwMe (result); 1001 } 1002 1003 CSSM_DB_MODIFY_MODE modifyMode = params->modifyMode; 1004 1005 // parse the key data blob 1006 CssmDataContainer keyBlob; 1007 data.Length = GetUInt32AtFinger (finger); 1008 data.Data = finger; 1009 1010 CSSM_DB_RECORD_ATTRIBUTE_DATA* attrDataPtr = NULL; 1011 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; 1012 1013 CSSM_DATA labelData = {kLabelSize, oldData.Data}; 1014 CSSM_DB_UNIQUE_RECORD_PTR recordID; 1015 getUniqueIdForSymmetricKey (db, labelData, recordID); 1016 1017 CSSM_DB_ATTRIBUTE_DATA_PTR keyAttributes; 1018 uint32 numKeyAttributes; 1019 unwrapAttributesAndData (numKeyAttributes, keyAttributes, keyBlob, data); 1020 1021 // make the attribute data 1022 attrData.DataRecordType = params->recordType; 1023 attrData.SemanticInformation = 0; 1024 attrData.NumberOfAttributes = numKeyAttributes; 1025 attrData.AttributeData = keyAttributes; 1026 1027 attrDataPtr = &attrData; 1028 1029 result = CSSM_DL_DataModify (db->handle(), 1030 CSSM_DL_DB_RECORD_SYMMETRIC_KEY, 1031 recordID, 1032 attrDataPtr, 1033 &keyBlob, 1034 modifyMode); 1035 1036 // clean up 1037 CSSM_DL_FreeUniqueRecord (db->handle (), recordID); 1038 1039 cleanupAttributes (numKeyAttributes, keyAttributes); 1040 break; 1041 } 1042 1043 default: 1044 { 1045 break; 1046 } 1047 } 1048 1049 // save off the new data 1050 result = CSSM_DL_DataModify(db->handle(), 1051 params->recordType, 1052 uniqueIDPtr, 1053 &attrData, 1054 &dataBlob, 1055 params->modifyMode); 1056 1057 // clean up 1058 cleanupAttributes (numAttributes, attributes); 1059 1060 if (result) 1061 { 1062 CssmError::throwMe(result); 1063 } 1064 1065} 1066 1067void 1068SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams) 1069{ 1070 CSSM_RETURN result; 1071 1072 CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS* params = 1073 (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; 1074 1075 // extract the data for this insert. 1076 uint8* finger = params->data.Data; 1077 CSSM_DATA data; 1078 data.Length = GetUInt32AtFinger (finger); 1079 data.Data = finger; 1080 finger += data.Length; 1081 1082 // reconstruct the attributes and data 1083 uint32 numAttributes; 1084 CSSM_DB_ATTRIBUTE_DATA_PTR attributes; 1085 CSSM_DATA dataBlob; 1086 1087 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); 1088 1089 // make the attribute data 1090 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; 1091 attrData.DataRecordType = params->recordType; 1092 attrData.SemanticInformation = 0; 1093 attrData.NumberOfAttributes = numAttributes; 1094 attrData.AttributeData = attributes; 1095 1096 // insert into the database 1097 SSUniqueRecord uniqueID (db); 1098 result = CSSM_DL_DataInsert (db->handle(), params->recordType, 1099 &attrData, 1100 &dataBlob, 1101 uniqueID); 1102 1103 // cleanup 1104 allocator ().free (dataBlob.Data); 1105 cleanupAttributes (numAttributes, attributes); 1106 1107 // attach into the CSP/DL mechanism 1108 CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueID); 1109 *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord; 1110 1111 if (result) 1112 { 1113 CssmError::throwMe(result); 1114 } 1115 1116 // Get the key data for this insert 1117 data.Length = GetUInt32AtFinger (finger); 1118 if (data.Length != 0) 1119 { 1120 data.Data = finger; 1121 1122 // parse the key data blob 1123 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); 1124 1125 // make the attribute data 1126 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; 1127 attrData.DataRecordType = params->recordType; 1128 attrData.SemanticInformation = 0; 1129 attrData.NumberOfAttributes = numAttributes; 1130 attrData.AttributeData = attributes; 1131 1132 // insert the key data into the symmetric key table 1133 CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord; 1134 result = CSSM_DL_DataInsert (db->handle(), CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &attrData, &dataBlob, 1135 &uniqueRecord); 1136 if (result) 1137 { 1138 CssmError::throwMe (result); 1139 } 1140 1141 // clean up after inserting the key 1142 CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord); 1143 allocator ().free (dataBlob.Data); 1144 cleanupAttributes (numAttributes, attributes); 1145 } 1146} 1147 1148void 1149SSDLSession::doConvertRecordIdentifier (SSDatabase &db, const void *inInputParams, void **outOutputParams) 1150{ 1151 SSUniqueRecord uniqueId (db); 1152 1153 // clone the unique record 1154 CSSM_DB_UNIQUE_RECORD_PTR clone = (CSSM_DB_UNIQUE_RECORD_PTR) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD)); 1155 *clone = *(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams; 1156 1157 // set the value of the unique record 1158 uniqueId->setUniqueRecordPtr (clone); 1159 1160 // byte swap the retrieved record pointer to host order 1161 uint32* idArray = (uint32*) clone->RecordIdentifier.Data; 1162 idArray[0] = ntohl (idArray[0]); 1163 idArray[1] = ntohl (idArray[1]); 1164 idArray[2] = ntohl (idArray[2]); 1165 1166 CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueId); 1167 *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord; 1168} 1169 1170void 1171SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, 1172 uint32 inPassThroughId, 1173 const void *inInputParams, 1174 void **outOutputParams) 1175{ 1176 if (inPassThroughId == CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB) 1177 { 1178 CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS* params = (CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS*) inInputParams; 1179 CreateWithBlob(params->dbName, params->dbLocation, *params->dbInfo, params->accessRequest, params->openParameters, *params->blob, 1180 * (CSSM_DB_HANDLE*) outOutputParams); 1181 return; 1182 } 1183 1184 SSDatabase db = findDbHandle(inDbHandle); 1185 switch (inPassThroughId) 1186 { 1187 case CSSM_APPLECSPDL_DB_LOCK: 1188 db->lock(); 1189 break; 1190 case CSSM_APPLECSPDL_DB_UNLOCK: 1191 if (inInputParams) 1192 db->unlock(*reinterpret_cast<const CSSM_DATA *>(inInputParams)); 1193 else 1194 db->unlock(); 1195 break; 1196 case CSSM_APPLECSPDL_DB_STASH: 1197 db->stash(); 1198 break; 1199 case CSSM_APPLECSPDL_DB_STASH_CHECK: 1200 db->stashCheck(); 1201 break; 1202 case CSSM_APPLECSPDL_DB_GET_SETTINGS: 1203 { 1204 if (!outOutputParams) 1205 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER); 1206 1207 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR params = 1208 DatabaseSession::alloc<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS>(); 1209 try 1210 { 1211 uint32 idleTimeout; 1212 bool lockOnSleep; 1213 db->getSettings(idleTimeout, lockOnSleep); 1214 params->idleTimeout = idleTimeout; 1215 params->lockOnSleep = lockOnSleep; 1216 } 1217 catch(...) 1218 { 1219 allocator().free(params); 1220 throw; 1221 } 1222 *reinterpret_cast<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR *>(outOutputParams) = params; 1223 break; 1224 } 1225 case CSSM_APPLECSPDL_DB_SET_SETTINGS: 1226 { 1227 if (!inInputParams) 1228 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); 1229 1230 const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *params = 1231 reinterpret_cast<const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *>(inInputParams); 1232 db->setSettings(params->idleTimeout, params->lockOnSleep); 1233 break; 1234 } 1235 case CSSM_APPLECSPDL_DB_IS_LOCKED: 1236 { 1237 if (!outOutputParams) 1238 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER); 1239 1240 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params = 1241 DatabaseSession::alloc<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS>(); 1242 try 1243 { 1244 params->isLocked = db->isLocked(); 1245 } 1246 catch(...) 1247 { 1248 allocator().free(params); 1249 throw; 1250 } 1251 *reinterpret_cast<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR *>(outOutputParams) = params; 1252 break; 1253 } 1254 case CSSM_APPLECSPDL_DB_CHANGE_PASSWORD: 1255 { 1256 if (!inInputParams) 1257 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); 1258 1259 const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *params = 1260 reinterpret_cast<const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *>(inInputParams); 1261 db->changePassphrase(params->accessCredentials); 1262 break; 1263 } 1264 case CSSM_APPLECSPDL_DB_GET_HANDLE: 1265 { 1266 using SecurityServer::DbHandle; 1267 Required(outOutputParams, CSSM_ERRCODE_INVALID_OUTPUT_POINTER); 1268 *reinterpret_cast<CSSM_DL_DB_HANDLE *>(outOutputParams) = db->handle(); 1269 break; 1270 } 1271 case CSSM_APPLECSPDL_CSP_RECODE: 1272 { 1273 if (!inInputParams) 1274 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER); 1275 1276 const CSSM_APPLECSPDL_RECODE_PARAMETERS *params = 1277 reinterpret_cast<const CSSM_APPLECSPDL_RECODE_PARAMETERS *>(inInputParams); 1278 1279 db->recode(CssmData::overlay(params->dbBlob), 1280 CssmData::overlay(params->extraData)); 1281 break; 1282 } 1283 case CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER: 1284 { 1285 SSUniqueRecord uniqueID = findSSUniqueRecord(*(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams); 1286 db->getRecordIdentifier(uniqueID, *reinterpret_cast<CSSM_DATA *>(outOutputParams)); 1287 break; 1288 } 1289 case CSSM_APPLECSPDL_DB_COPY_BLOB: 1290 { 1291 // make the output parameters 1292 db->copyBlob(*reinterpret_cast<CSSM_DATA *>(outOutputParams)); 1293 break; 1294 } 1295 case CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION: 1296 { 1297 doInsertWithoutEncryption (db, inInputParams, outOutputParams); 1298 break; 1299 } 1300 case CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION: 1301 { 1302 doModifyWithoutEncryption (db, inInputParams, outOutputParams); 1303 break; 1304 } 1305 case CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION: 1306 { 1307 doGetWithoutEncryption (db, inInputParams, outOutputParams); 1308 break; 1309 } 1310 case CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER: 1311 { 1312 doConvertRecordIdentifier (db, inInputParams, outOutputParams); 1313 break; 1314 } 1315 default: 1316 { 1317 CSSM_RETURN result = CSSM_DL_PassThrough(db->handle(), inPassThroughId, inInputParams, outOutputParams); 1318 if (result) 1319 CssmError::throwMe(result); 1320 break; 1321 } 1322 } 1323} 1324 1325CSSM_DB_HANDLE 1326SSDLSession::makeDbHandle(SSDatabase &inDb) 1327{ 1328 StLock<Mutex> _(mDbHandleLock); 1329 CSSM_DB_HANDLE aDbHandle = inDb->handle().DBHandle; 1330 bool inserted; 1331 inserted = mDbHandleMap.insert(DbHandleMap::value_type(aDbHandle, inDb)).second; 1332 assert(inserted); 1333 // fprintf(stderr, "%p Added %p to %p\n", pthread_self(), (void*) aDbHandle, (void*) this); 1334 return aDbHandle; 1335} 1336 1337SSDatabase 1338SSDLSession::killDbHandle(CSSM_DB_HANDLE inDbHandle) 1339{ 1340 StLock<Mutex> _(mDbHandleLock); 1341 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle); 1342 if (it == mDbHandleMap.end()) 1343 { 1344 // fprintf(stderr, "Can't find %p in %p\n", (void*) inDbHandle, this); 1345 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE); 1346 } 1347 1348 SSDatabase db = it->second; 1349 // fprintf(stderr, "%p Removed %p from %p\n", pthread_self(), (void*) it->first, (void*) this); 1350 mDbHandleMap.erase(it); 1351 return db; 1352} 1353 1354SSDatabase 1355SSDLSession::findDbHandle(CSSM_DB_HANDLE inDbHandle) 1356{ 1357 StLock<Mutex> _(mDbHandleLock); 1358 // fprintf(stderr, "%p Looking for %p in %p\n", pthread_self(), (void*) inDbHandle, (void*) this); 1359 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle); 1360 if (it == mDbHandleMap.end()) 1361 { 1362 // fprintf(stderr, "%p Can't find %p in %p\n", pthread_self(), (void*) inDbHandle, this); 1363 DbHandleMap::iterator it = mDbHandleMap.begin(); 1364 while (it != mDbHandleMap.end()) 1365 { 1366 // fprintf(stderr, "\t%p\n", (void*) it->first); 1367 it++; 1368 } 1369 1370 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE); 1371 } 1372 1373 return it->second; 1374} 1375 1376CSSM_DB_UNIQUE_RECORD_PTR 1377SSDLSession::makeSSUniqueRecord(SSUniqueRecord &uniqueId) 1378{ 1379 StLock<Mutex> _(mSSUniqueRecordLock); 1380 CSSM_HANDLE ref = CSSM_HANDLE(static_cast<CSSM_DB_UNIQUE_RECORD *>(uniqueId)); 1381 bool inserted; 1382 inserted = mSSUniqueRecordMap.insert(SSUniqueRecordMap::value_type(ref, uniqueId)).second; 1383 assert(inserted); 1384 return createUniqueRecord(ref); 1385} 1386 1387SSUniqueRecord 1388SSDLSession::killSSUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord) 1389{ 1390 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord); 1391 StLock<Mutex> _(mSSUniqueRecordLock); 1392 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref); 1393 if (it == mSSUniqueRecordMap.end()) 1394 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); 1395 1396 SSUniqueRecord uniqueRecord = it->second; 1397 mSSUniqueRecordMap.erase(it); 1398 freeUniqueRecord(inUniqueRecord); 1399 return uniqueRecord; 1400} 1401 1402SSUniqueRecord 1403SSDLSession::findSSUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord) 1404{ 1405 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord); 1406 StLock<Mutex> _(mSSUniqueRecordLock); 1407 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref); 1408 if (it == mSSUniqueRecordMap.end()) 1409 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); 1410 1411 return it->second; 1412} 1413 1414CSSM_DB_UNIQUE_RECORD_PTR 1415SSDLSession::createUniqueRecord(CSSM_HANDLE ref) 1416{ 1417 CSSM_DB_UNIQUE_RECORD *aUniqueRecord = DatabaseSession::alloc<CSSM_DB_UNIQUE_RECORD>(); 1418 memset(aUniqueRecord, 0, sizeof(CSSM_DB_UNIQUE_RECORD)); 1419 aUniqueRecord->RecordIdentifier.Length = sizeof(CSSM_HANDLE); 1420 try 1421 { 1422 aUniqueRecord->RecordIdentifier.Data = DatabaseSession::alloc<uint8>(sizeof(CSSM_HANDLE)); 1423 *reinterpret_cast<CSSM_HANDLE *>(aUniqueRecord->RecordIdentifier.Data) = ref; 1424 } 1425 catch(...) 1426 { 1427 free(aUniqueRecord); 1428 throw; 1429 } 1430 1431 return aUniqueRecord; 1432} 1433 1434CSSM_HANDLE 1435SSDLSession::parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord) 1436{ 1437 if (inUniqueRecord.RecordIdentifier.Length != sizeof(CSSM_HANDLE)) 1438 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID); 1439 1440 return *reinterpret_cast<CSSM_HANDLE *>(inUniqueRecord.RecordIdentifier.Data); 1441} 1442 1443void 1444SSDLSession::freeUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord) 1445{ 1446 if (inUniqueRecord.RecordIdentifier.Length != 0 1447 && inUniqueRecord.RecordIdentifier.Data != NULL) 1448 { 1449 inUniqueRecord.RecordIdentifier.Length = 0; 1450 allocator().free(inUniqueRecord.RecordIdentifier.Data); 1451 } 1452 allocator().free(&inUniqueRecord); 1453} 1454