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