]> git.saurik.com Git - apple/security.git/blob - AppleCSPDL/SSDLSession.cpp
Security-164.1.tar.gz
[apple/security.git] / AppleCSPDL / SSDLSession.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // SSDLSession.h - DL session for security server CSP/DL.
21 //
22 #include "SSDLSession.h"
23
24 #include "CSPDLPlugin.h"
25 #include "SSKey.h"
26
27 using namespace CssmClient;
28 using namespace SecurityServer;
29 using namespace std;
30
31 //
32 // SSDLSession -- Security Server DL session
33 //
34 SSDLSession::SSDLSession(CSSM_MODULE_HANDLE handle,
35 CSPDLPlugin &plug,
36 const CSSM_VERSION &version,
37 uint32 subserviceId,
38 CSSM_SERVICE_TYPE subserviceType,
39 CSSM_ATTACH_FLAGS attachFlags,
40 const CSSM_UPCALLS &upcalls,
41 DatabaseManager &databaseManager,
42 SSCSPDLSession &ssCSPDLSession)
43 : DLPluginSession(handle, plug, version, subserviceId, subserviceType,
44 attachFlags, upcalls, databaseManager),
45 mSSCSPDLSession(ssCSPDLSession),
46 mDL(Module(gGuidAppleFileDL, Cssm::standard())),
47 mClientSession(CssmAllocator::standard(), static_cast<PluginSession &>(*this))
48 {
49 mClientSession.registerForAclEdits(SSCSPDLSession::didChangeKeyAclCallback, &mSSCSPDLSession);
50 // @@@ mDL.allocator(*static_cast<DatabaseSession *>(this));
51 mDL->allocator(allocator());
52 mDL->version(version);
53 mDL->subserviceId(subserviceId);
54 mDL->flags(attachFlags);
55 }
56
57 SSDLSession::~SSDLSession()
58 {
59 // @@@ What about a catch?
60 StLock<Mutex> _1(mSSUniqueRecordLock);
61 mSSUniqueRecordMap.clear();
62
63 StLock<Mutex> _2(mDbHandleLock);
64 DbHandleMap::iterator end = mDbHandleMap.end();
65 for (DbHandleMap::iterator it = mDbHandleMap.begin(); it != end; ++it)
66 it->second->close();
67
68 mDbHandleMap.clear();
69 mDL->detach();
70 }
71
72 // Utility functions
73 void
74 SSDLSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList)
75 {
76 // @@@ Fix client lib
77 CSSM_DL_GetDbNames(mDL->handle(), &outNameList);
78 }
79
80
81 void
82 SSDLSession::FreeNameList(CSSM_NAME_LIST &inNameList)
83 {
84 // @@@ Fix client lib
85 CSSM_DL_FreeNameList(mDL->handle(), &inNameList);
86 }
87
88
89 void
90 SSDLSession::DbDelete(const char *inDbName,
91 const CSSM_NET_ADDRESS *inDbLocation,
92 const AccessCredentials *inAccessCred)
93 {
94 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation);
95 db->accessCredentials(inAccessCred);
96 db->deleteDb();
97 }
98
99 // DbContext creation and destruction.
100 void
101 SSDLSession::DbCreate(const char *inDbName,
102 const CSSM_NET_ADDRESS *inDbLocation,
103 const CSSM_DBINFO &inDBInfo,
104 CSSM_DB_ACCESS_TYPE inAccessRequest,
105 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
106 const void *inOpenParameters,
107 CSSM_DB_HANDLE &outDbHandle)
108 {
109 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation);
110 db->dbInfo(&inDBInfo);
111 db->accessRequest(inAccessRequest);
112 db->resourceControlContext(inCredAndAclEntry);
113 db->openParameters(inOpenParameters);
114 db->create(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(),
115 CSSM_SERVICE_DL | CSSM_SERVICE_CSP),
116 inDbName, inDbLocation));
117 db->dbInfo(NULL);
118 outDbHandle = makeDbHandle(db);
119 }
120
121 void
122 SSDLSession::DbOpen(const char *inDbName,
123 const CSSM_NET_ADDRESS *inDbLocation,
124 CSSM_DB_ACCESS_TYPE inAccessRequest,
125 const AccessCredentials *inAccessCred,
126 const void *inOpenParameters,
127 CSSM_DB_HANDLE &outDbHandle)
128 {
129 SSDatabase db(mClientSession, mDL, inDbName, inDbLocation);
130 db->accessRequest(inAccessRequest);
131 db->accessCredentials(inAccessCred);
132 db->openParameters(inOpenParameters);
133 db->open(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(),
134 CSSM_SERVICE_DL | CSSM_SERVICE_CSP),
135 inDbName, inDbLocation));
136 outDbHandle = makeDbHandle(db);
137 }
138
139 // Operations using DbContext instances.
140 void
141 SSDLSession::DbClose(CSSM_DB_HANDLE inDbHandle)
142 {
143 killDbHandle(inDbHandle)->close();
144 }
145
146 void
147 SSDLSession::CreateRelation(CSSM_DB_HANDLE inDbHandle,
148 CSSM_DB_RECORDTYPE inRelationID,
149 const char *inRelationName,
150 uint32 inNumberOfAttributes,
151 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO &inAttributeInfo,
152 uint32 inNumberOfIndexes,
153 const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo)
154 {
155 SSDatabase db = findDbHandle(inDbHandle);
156 // @@@ Fix inAttributeInfo and inIndexInfo arguments (might be NULL if NumberOf = 0)
157 db->createRelation(inRelationID, inRelationName,
158 inNumberOfAttributes, &inAttributeInfo,
159 inNumberOfIndexes, &inIndexInfo);
160 }
161
162 void
163 SSDLSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle,
164 CSSM_DB_RECORDTYPE inRelationID)
165 {
166 // @@@ Check credentials.
167 SSDatabase db = findDbHandle(inDbHandle);
168 db->destroyRelation(inRelationID);
169 }
170
171 void
172 SSDLSession::Authenticate(CSSM_DB_HANDLE inDbHandle,
173 CSSM_DB_ACCESS_TYPE inAccessRequest,
174 const AccessCredentials &inAccessCred)
175 {
176 SSDatabase db = findDbHandle(inDbHandle);
177 db->authenticate(inAccessRequest, &inAccessCred);
178 }
179
180
181 void
182 SSDLSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle,
183 const CSSM_STRING *inSelectionTag,
184 uint32 &outNumberOfAclInfos,
185 CSSM_ACL_ENTRY_INFO_PTR &outAclInfos)
186 {
187 SSDatabase db = findDbHandle(inDbHandle);
188 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
189 }
190
191 void
192 SSDLSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle,
193 const AccessCredentials &inAccessCred,
194 const CSSM_ACL_EDIT &inAclEdit)
195 {
196 SSDatabase db = findDbHandle(inDbHandle);
197 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
198 }
199
200 void
201 SSDLSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle,
202 CSSM_ACL_OWNER_PROTOTYPE &outOwner)
203 {
204 SSDatabase db = findDbHandle(inDbHandle);
205 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
206 }
207
208 void
209 SSDLSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle,
210 const AccessCredentials &inAccessCred,
211 const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner)
212 {
213 SSDatabase db = findDbHandle(inDbHandle);
214 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
215 }
216
217 void
218 SSDLSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle,
219 char **outDbName)
220 {
221 SSDatabase db = findDbHandle(inDbHandle);
222 // @@@ Fix this functions signature.
223 db->name(*outDbName);
224 }
225
226 void
227 SSDLSession::DataInsert(CSSM_DB_HANDLE inDbHandle,
228 CSSM_DB_RECORDTYPE inRecordType,
229 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
230 const CssmData *inData,
231 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId)
232 {
233 SSDatabase db = findDbHandle(inDbHandle);
234 // @@@ Fix client lib.
235 SSUniqueRecord uniqueId = db->insert(inRecordType, inAttributes, inData, true); // @@@ Fix me
236 outUniqueId = makeSSUniqueRecord(uniqueId);
237 // @@@ If this is a key do the right thing.
238 }
239
240 void
241 SSDLSession::DataDelete(CSSM_DB_HANDLE inDbHandle,
242 const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
243 {
244 SSDatabase db = findDbHandle(inDbHandle);
245 SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecordIdentifier);
246 uniqueId->deleteRecord();
247 // @@@ If this is a key do the right thing.
248 }
249
250
251 void
252 SSDLSession::DataModify(CSSM_DB_HANDLE inDbHandle,
253 CSSM_DB_RECORDTYPE inRecordType,
254 CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier,
255 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified,
256 const CssmData *inDataToBeModified,
257 CSSM_DB_MODIFY_MODE inModifyMode)
258 {
259 SSDatabase db = findDbHandle(inDbHandle);
260 SSUniqueRecord uniqueId = findSSUniqueRecord(inoutUniqueRecordIdentifier);
261 uniqueId->modify(inRecordType, inAttributesToBeModified, inDataToBeModified, inModifyMode);
262 // @@@ If this is a key do the right thing.
263 }
264
265 CSSM_HANDLE
266 SSDLSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle,
267 const DLQuery *inQuery,
268 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
269 CssmData *inoutData,
270 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord)
271 {
272 SSDatabase db = findDbHandle(inDbHandle);
273 CSSM_HANDLE resultsHandle = CSSM_INVALID_HANDLE;
274 SSUniqueRecord uniqueId(db);
275
276 // Setup so we always retrive the attributes even if the client
277 // doesn't want them so we can figure out if we just retrived a key.
278 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes;
279 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes;
280 if (inoutAttributes)
281 pAttributes = inoutAttributes;
282 else
283 {
284 pAttributes = &attributes;
285 memset(pAttributes, 0, sizeof(attributes));
286 }
287
288 // Retrive the record.
289 CSSM_RETURN result = CSSM_DL_DataGetFirst(db->handle(), inQuery, &resultsHandle,
290 pAttributes, inoutData, uniqueId);
291 if (result)
292 {
293 if (result == CSSMERR_DL_ENDOFDATA)
294 return CSSM_INVALID_HANDLE;
295
296 CssmError::throwMe(result);
297 }
298
299 uniqueId->activate();
300
301 // If we the client didn't ask for data then it doesn't matter
302 // if this record is a key or not, just return it.
303 if (inoutData)
304 {
305 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY
306 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY
307 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY)
308 {
309 // This record is a key, do the right thing (tm).
310 // Allocate storage for the key.
311 CssmKey *outKey = allocator().alloc<CssmKey>();
312 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData);
313
314 // Free the data we retrived (keyblob)
315 allocator().free(inoutData->Data);
316
317 // Set the length and data on the data we return to the client
318 inoutData->Length = sizeof(*outKey);
319 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
320 }
321 }
322
323 outUniqueRecord = makeSSUniqueRecord(uniqueId);
324 return resultsHandle;
325 }
326
327 bool
328 SSDLSession::DataGetNext(CSSM_DB_HANDLE inDbHandle,
329 CSSM_HANDLE inResultsHandle,
330 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
331 CssmData *inoutData,
332 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord)
333 {
334 // @@@ If this is a key do the right thing.
335 SSDatabase db = findDbHandle(inDbHandle);
336 SSUniqueRecord uniqueId(db);
337
338 // Setup so we always retrive the attributes even if the client
339 // doesn't want them so we can figure out if we just retrived a key.
340 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes;
341 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes;
342 if (inoutAttributes)
343 pAttributes = inoutAttributes;
344 else
345 {
346 pAttributes = &attributes;
347 memset(pAttributes, 0, sizeof(attributes));
348 }
349
350 CSSM_RETURN result = CSSM_DL_DataGetNext(db->handle(), inResultsHandle,
351 inoutAttributes, inoutData, uniqueId);
352 if (result)
353 {
354 if (result == CSSMERR_DL_ENDOFDATA)
355 return false;
356
357 CssmError::throwMe(result);
358 }
359
360 uniqueId->activate();
361
362 // If we the client didn't ask for data then it doesn't matter
363 // if this record is a key or not, just return it.
364 if (inoutData)
365 {
366 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY
367 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY
368 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY)
369 {
370 // This record is a key, do the right thing (tm).
371 // Allocate storage for the key.
372 CssmKey *outKey = allocator().alloc<CssmKey>();
373 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData);
374
375 // Free the data we retrived (keyblob)
376 allocator().free(inoutData->Data);
377
378 // Set the length and data on the data we return to the client
379 inoutData->Length = sizeof(*outKey);
380 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
381 }
382 }
383
384 outUniqueRecord = makeSSUniqueRecord(uniqueId);
385
386 return true;
387 }
388
389 void
390 SSDLSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle,
391 CSSM_HANDLE inResultsHandle)
392 {
393 // @@@ If this is a key do the right thing.
394 SSDatabase db = findDbHandle(inDbHandle);
395 CSSM_RETURN result = CSSM_DL_DataAbortQuery(db->handle(), inResultsHandle);
396 if (result)
397 CssmError::throwMe(result);
398 }
399
400 void
401 SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle,
402 const CSSM_DB_UNIQUE_RECORD &inUniqueRecord,
403 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
404 CssmData *inoutData)
405 {
406 SSDatabase db = findDbHandle(inDbHandle);
407 const SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecord);
408
409 // Setup so we always retrive the attributes even if the client
410 // doesn't want them so we can figure out if we just retrived a key.
411 CSSM_DB_RECORD_ATTRIBUTE_DATA attributes;
412 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR pAttributes;
413 if (inoutAttributes)
414 pAttributes = inoutAttributes;
415 else
416 {
417 pAttributes = &attributes;
418 memset(pAttributes, 0, sizeof(attributes));
419 }
420
421 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(),
422 uniqueId, pAttributes, inoutData);
423 if (result)
424 CssmError::throwMe(result);
425
426 if (inoutData)
427 {
428 if (pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PUBLIC_KEY
429 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_PRIVATE_KEY
430 || pAttributes->DataRecordType == CSSM_DL_DB_RECORD_SYMMETRIC_KEY)
431 {
432 // This record is a key, do the right thing (tm).
433 // Allocate storage for the key.
434 CssmKey *outKey = allocator().alloc<CssmKey>();
435 new SSKey(*this, *outKey, db, uniqueId, pAttributes->DataRecordType, *inoutData);
436
437 // Free the data we retrived (keyblob)
438 allocator().free(inoutData->Data);
439
440 // Set the length and data on the data we return to the client
441 inoutData->Length = sizeof(*outKey);
442 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
443 }
444 }
445 }
446
447 void
448 SSDLSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle,
449 CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
450 {
451 killSSUniqueRecord(inUniqueRecordIdentifier);
452 }
453
454 void
455 SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle,
456 uint32 inPassThroughId,
457 const void *inInputParams,
458 void **outOutputParams)
459 {
460 SSDatabase db = findDbHandle(inDbHandle);
461 switch (inPassThroughId)
462 {
463 case CSSM_APPLECSPDL_DB_LOCK:
464 db->lock();
465 break;
466 case CSSM_APPLECSPDL_DB_UNLOCK:
467 if (inInputParams)
468 db->unlock(*reinterpret_cast<const CSSM_DATA *>(inInputParams));
469 else
470 db->unlock();
471 break;
472 case CSSM_APPLECSPDL_DB_GET_SETTINGS:
473 {
474 if (!outOutputParams)
475 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
476
477 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR params =
478 allocator().alloc<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS>();
479 try
480 {
481 uint32 idleTimeout;
482 bool lockOnSleep;
483 db->getSettings(idleTimeout, lockOnSleep);
484 params->idleTimeout = idleTimeout;
485 params->lockOnSleep = lockOnSleep;
486 }
487 catch(...)
488 {
489 allocator().free(params);
490 throw;
491 }
492 *reinterpret_cast<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR *>(outOutputParams) = params;
493 break;
494 }
495 case CSSM_APPLECSPDL_DB_SET_SETTINGS:
496 {
497 if (!inInputParams)
498 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER);
499
500 const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *params =
501 reinterpret_cast<const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *>(inInputParams);
502 db->setSettings(params->idleTimeout, params->lockOnSleep);
503 break;
504 }
505 case CSSM_APPLECSPDL_DB_IS_LOCKED:
506 {
507 if (!outOutputParams)
508 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
509
510 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params =
511 allocator().alloc<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS>();
512 try
513 {
514 params->isLocked = db->isLocked();
515 }
516 catch(...)
517 {
518 allocator().free(params);
519 throw;
520 }
521 *reinterpret_cast<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR *>(outOutputParams) = params;
522 break;
523 }
524 case CSSM_APPLECSPDL_DB_CHANGE_PASSWORD:
525 {
526 if (!inInputParams)
527 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER);
528
529 const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *params =
530 reinterpret_cast<const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *>(inInputParams);
531 db->changePassphrase(params->accessCredentials);
532 break;
533 }
534 case CSSM_APPLECSPDL_DB_GET_HANDLE:
535 {
536 using SecurityServer::DbHandle;
537 Required(outOutputParams, CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
538 DbHandle &dbHandle = *(DbHandle *)outOutputParams;
539 dbHandle = db->dbHandle();
540 break;
541 }
542 default:
543 {
544 CSSM_RETURN result = CSSM_DL_PassThrough(db->handle(), inPassThroughId, inInputParams, outOutputParams);
545 if (result)
546 CssmError::throwMe(result);
547 break;
548 }
549 }
550 }
551
552 CSSM_DB_HANDLE
553 SSDLSession::makeDbHandle(SSDatabase &inDb)
554 {
555 StLock<Mutex> _(mDbHandleLock);
556 CSSM_DB_HANDLE aDbHandle = inDb->handle().DBHandle;
557 IFDEBUG(bool inserted =) mDbHandleMap.insert(DbHandleMap::value_type(aDbHandle, inDb)).second;
558 assert(inserted);
559 return aDbHandle;
560 }
561
562 SSDatabase
563 SSDLSession::killDbHandle(CSSM_DB_HANDLE inDbHandle)
564 {
565 StLock<Mutex> _(mDbHandleLock);
566 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle);
567 if (it == mDbHandleMap.end())
568 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
569
570 SSDatabase db = it->second;
571 mDbHandleMap.erase(it);
572 return db;
573 }
574
575 SSDatabase
576 SSDLSession::findDbHandle(CSSM_DB_HANDLE inDbHandle)
577 {
578 StLock<Mutex> _(mDbHandleLock);
579 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle);
580 if (it == mDbHandleMap.end())
581 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
582
583 return it->second;
584 }
585
586 CSSM_DB_UNIQUE_RECORD_PTR
587 SSDLSession::makeSSUniqueRecord(SSUniqueRecord &uniqueId)
588 {
589 StLock<Mutex> _(mSSUniqueRecordLock);
590 CSSM_HANDLE ref = CSSM_HANDLE(static_cast<CSSM_DB_UNIQUE_RECORD *>(uniqueId));
591 IFDEBUG(bool inserted =) mSSUniqueRecordMap.insert(SSUniqueRecordMap::value_type(ref, uniqueId)).second;
592 assert(inserted);
593 return createUniqueRecord(ref);
594 }
595
596 SSUniqueRecord
597 SSDLSession::killSSUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
598 {
599 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord);
600 StLock<Mutex> _(mSSUniqueRecordLock);
601 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref);
602 if (it == mSSUniqueRecordMap.end())
603 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
604
605 SSUniqueRecord uniqueRecord = it->second;
606 mSSUniqueRecordMap.erase(it);
607 freeUniqueRecord(inUniqueRecord);
608 return uniqueRecord;
609 }
610
611 SSUniqueRecord
612 SSDLSession::findSSUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
613 {
614 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord);
615 StLock<Mutex> _(mSSUniqueRecordLock);
616 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref);
617 if (it == mSSUniqueRecordMap.end())
618 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
619
620 return it->second;
621 }
622
623 CSSM_DB_UNIQUE_RECORD_PTR
624 SSDLSession::createUniqueRecord(CSSM_HANDLE ref)
625 {
626 CSSM_DB_UNIQUE_RECORD *aUniqueRecord = allocator().alloc<CSSM_DB_UNIQUE_RECORD>();
627 memset(aUniqueRecord, 0, sizeof(CSSM_DB_UNIQUE_RECORD));
628 aUniqueRecord->RecordIdentifier.Length = sizeof(CSSM_HANDLE);
629 try
630 {
631 aUniqueRecord->RecordIdentifier.Data = allocator().alloc<uint8>(sizeof(CSSM_HANDLE));
632 *reinterpret_cast<CSSM_HANDLE *>(aUniqueRecord->RecordIdentifier.Data) = ref;
633 }
634 catch(...)
635 {
636 free(aUniqueRecord);
637 throw;
638 }
639
640 return aUniqueRecord;
641 }
642
643 CSSM_HANDLE
644 SSDLSession::parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
645 {
646 if (inUniqueRecord.RecordIdentifier.Length != sizeof(CSSM_HANDLE))
647 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
648
649 return *reinterpret_cast<CSSM_HANDLE *>(inUniqueRecord.RecordIdentifier.Data);
650 }
651
652 void
653 SSDLSession::freeUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
654 {
655 if (inUniqueRecord.RecordIdentifier.Length != 0
656 && inUniqueRecord.RecordIdentifier.Data != NULL)
657 {
658 inUniqueRecord.RecordIdentifier.Length = 0;
659 allocator().free(inUniqueRecord.RecordIdentifier.Data);
660 }
661 allocator().free(&inUniqueRecord);
662 }