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