]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_apple_cspdl/lib/SSDLSession.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / Security / libsecurity_apple_cspdl / lib / SSDLSession.cpp
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
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 try
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 }
74 catch (...)
75 {
76 }
77
78 // Utility functions
79 void
80 SSDLSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList)
81 {
82 // @@@ Fix client lib
83 CSSM_DL_GetDbNames(mDL->handle(), &outNameList);
84 }
85
86
87 void
88 SSDLSession::FreeNameList(CSSM_NAME_LIST &inNameList)
89 {
90 // @@@ Fix client lib
91 CSSM_DL_FreeNameList(mDL->handle(), &inNameList);
92 }
93
94
95 void
96 SSDLSession::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.
106 void
107 SSDLSession::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
128 void
129 SSDLSession::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
151 void
152 SSDLSession::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.
171 void
172 SSDLSession::DbClose(CSSM_DB_HANDLE inDbHandle)
173 {
174 killDbHandle(inDbHandle)->close();
175 }
176
177 void
178 SSDLSession::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
193 void
194 SSDLSession::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
202 void
203 SSDLSession::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
212 void
213 SSDLSession::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
224 void
225 SSDLSession::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
233 void
234 SSDLSession::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
242 void
243 SSDLSession::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
252 void
253 SSDLSession::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
261 void
262 SSDLSession::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
275 void
276 SSDLSession::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
286 void
287 SSDLSession::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
300 CSSM_HANDLE
301 SSDLSession::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
362 bool
363 SSDLSession::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
424 void
425 SSDLSession::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
435 void
436 SSDLSession::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
482 void
483 SSDLSession::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
492 static const uint32 kGenericAttributeNames[] =
493 {
494 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce',
495 'gena'
496 };
497
498 const uint32 kNumGenericAttributes = sizeof (kGenericAttributeNames) / sizeof (uint32);
499
500 static 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
506 const uint32 kNumApplesharePasswordAttributes = sizeof (kApplesharePasswordNames) / sizeof (uint32);
507
508 static 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
514 const uint32 kNumInternetPasswordAttributes = sizeof (kInternetPasswordNames) / sizeof (uint32);
515
516 const 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
521 const uint32 kNumKeyAttributes = sizeof (kKeyAttributeNames) / sizeof (uint32);
522
523 const uint32 kCertificateAttributeNames[] =
524 {
525 'ctyp', 'cenc', 'labl', 'alis', 'subj', 'issu', 'snbr', 'skid', 'hpky'
526 };
527
528 const uint32 kNumCertificateAttributes = sizeof (kCertificateAttributeNames) / sizeof (uint32);
529
530 const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key
531 const unsigned kLabelSize = 20;
532 const unsigned kNumSymmetricAttributes = 27; // number of attributes to request
533
534 #pragma clang diagnostic pop
535
536 static void appendUInt32ToData (const uint32 value, CssmDataContainer &data)
537 {
538 data.append (CssmPolyData (uint32 (htonl (value))));
539 }
540
541 static 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
548 void
549 SSDLSession::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
644 void
645 SSDLSession::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
807 void
808 SSDLSession::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
847 void
848 SSDLSession::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
861 void 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
930 void
931 SSDLSession::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
948 void
949 SSDLSession::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
1067 void
1068 SSDLSession::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
1148 void
1149 SSDLSession::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
1170 void
1171 SSDLSession::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
1325 CSSM_DB_HANDLE
1326 SSDLSession::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
1337 SSDatabase
1338 SSDLSession::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
1354 SSDatabase
1355 SSDLSession::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
1376 CSSM_DB_UNIQUE_RECORD_PTR
1377 SSDLSession::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
1387 SSUniqueRecord
1388 SSDLSession::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
1402 SSUniqueRecord
1403 SSDLSession::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
1414 CSSM_DB_UNIQUE_RECORD_PTR
1415 SSDLSession::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
1434 CSSM_HANDLE
1435 SSDLSession::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
1443 void
1444 SSDLSession::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 }