]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_cspdl/lib/SSDLSession.cpp
Security-55471.14.18.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 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 static const uint32 kGenericAttributeNames[] =
490 {
491 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce',
492 'gena'
493 };
494
495 const uint32 kNumGenericAttributes = sizeof (kGenericAttributeNames) / sizeof (uint32);
496
497 static const uint32 kApplesharePasswordNames[] =
498 {
499 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'vlme',
500 'srvr', 'ptcl', 'addr', 'ssig'
501 };
502
503 const uint32 kNumApplesharePasswordAttributes = sizeof (kApplesharePasswordNames) / sizeof (uint32);
504
505 static const uint32 kInternetPasswordNames[] =
506 {
507 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'sdmn',
508 'srvr', 'ptcl', 'atyp', 'port', 'path'
509 };
510
511 const uint32 kNumInternetPasswordAttributes = sizeof (kInternetPasswordNames) / sizeof (uint32);
512
513 const uint32 kKeyAttributeNames[] =
514 {
515 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
516 };
517
518 const uint32 kNumKeyAttributes = sizeof (kKeyAttributeNames) / sizeof (uint32);
519
520 const uint32 kCertificateAttributeNames[] =
521 {
522 'ctyp', 'cenc', 'labl', 'alis', 'subj', 'issu', 'snbr', 'skid', 'hpky'
523 };
524
525 const uint32 kNumCertificateAttributes = sizeof (kCertificateAttributeNames) / sizeof (uint32);
526
527 const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key
528 const unsigned kLabelSize = 20;
529 const unsigned kNumSymmetricAttributes = 27; // number of attributes to request
530
531 static void appendUInt32ToData (const uint32 value, CssmDataContainer &data)
532 {
533 data.append (CssmPolyData (uint32 (htonl (value))));
534 }
535
536 static inline uint32 GetUInt32AtFinger (uint8 *&finger)
537 {
538 uint32 a = ((finger[0] << 24) | (finger[1] << 16) | (finger[2] << 8) | finger[3]);
539 finger += sizeof (uint32);
540 return a;
541 }
542
543 void
544 SSDLSession::unwrapAttributesAndData (uint32 &numAttributes,
545 CSSM_DB_ATTRIBUTE_DATA_PTR &attributes,
546 CSSM_DATA &data,
547 CSSM_DATA &input)
548 {
549 // get the number of attributes
550 uint8* finger = input.Data;
551 numAttributes = GetUInt32AtFinger (finger);
552
553 // compute the end of the data for sanity checking later
554 uint8* maximum = input.Data + input.Length;
555
556 // make the attribute array
557 attributes = (CSSM_DB_ATTRIBUTE_DATA*) allocator ().malloc (numAttributes * sizeof (CSSM_DB_ATTRIBUTE_DATA));
558
559 // for each attribute, retrieve the name format, name, type, and number of values
560 unsigned i;
561 for (i = 0; i < numAttributes; ++i)
562 {
563 attributes[i].Info.AttributeNameFormat = GetUInt32AtFinger (finger);
564 attributes[i].Info.Label.AttributeID = GetUInt32AtFinger (finger);
565 attributes[i].Info.AttributeFormat = GetUInt32AtFinger (finger);
566 attributes[i].NumberOfValues = GetUInt32AtFinger (finger);
567
568 // for each value, get the length and data
569 attributes[i].Value = (CSSM_DATA*) allocator ().malloc (sizeof (CSSM_DATA) * attributes[i].NumberOfValues);
570 unsigned j;
571 for (j = 0; j < attributes[i].NumberOfValues; ++j)
572 {
573 attributes[i].Value[j].Length = GetUInt32AtFinger (finger);
574 if (attributes[i].Value[j].Length != 0)
575 {
576 // sanity check what we are about to do
577 if (finger > maximum || finger + attributes[i].Value[j].Length > maximum)
578 {
579 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER);
580 }
581
582 attributes[i].Value[j].Data = (uint8*) allocator ().malloc (attributes[i].Value[j].Length);
583
584 switch (attributes[i].Info.AttributeFormat)
585 {
586 default:
587 {
588 memmove (attributes[i].Value[j].Data, finger, attributes[i].Value[j].Length);
589 finger += attributes[i].Value[j].Length;
590 break;
591 }
592
593 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
594 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
595 {
596 *(uint32*) attributes[i].Value[j].Data = GetUInt32AtFinger (finger);
597 break;
598 }
599
600 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
601 {
602 uint32* d = (uint32*) attributes[i].Value[j].Data;
603 unsigned long numValues = attributes[i].Value[j].Length / sizeof (UInt32);
604 while (numValues--)
605 {
606 *d++ = GetUInt32AtFinger (finger);
607 }
608 break;
609 }
610 }
611 }
612 else
613 {
614 attributes[i].Value[j].Data = NULL;
615 }
616 }
617 }
618
619 // get the data
620 data.Length = GetUInt32AtFinger (finger);
621 if (data.Length != 0)
622 {
623 // sanity check the pointer
624 if (finger + data.Length > maximum)
625 {
626 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER);
627 }
628
629 data.Data = (uint8*) allocator ().malloc (data.Length);
630 memmove (data.Data, finger, data.Length);
631 finger += data.Length;
632 }
633 else
634 {
635 data.Data = NULL;
636 }
637 }
638
639 void
640 SSDLSession::getWrappedAttributesAndData (SSDatabase &db,
641 CSSM_DB_RECORDTYPE recordType,
642 CSSM_DB_UNIQUE_RECORD_PTR recordPtr,
643 CssmDataContainer &output,
644 CSSM_DATA *dataBlob)
645 {
646 // figure out which attributes to use
647 const uint32* attributeNameArray;
648 uint32 numAttributeNames;
649
650 switch (recordType)
651 {
652 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD:
653 {
654 attributeNameArray = kGenericAttributeNames;
655 numAttributeNames = kNumGenericAttributes;
656 break;
657 }
658
659 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD:
660 {
661 attributeNameArray = kInternetPasswordNames;
662 numAttributeNames = kNumInternetPasswordAttributes;
663 break;
664 }
665
666 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD:
667 {
668 attributeNameArray = kApplesharePasswordNames;
669 numAttributeNames = kNumApplesharePasswordAttributes;
670 break;
671 }
672
673 case CSSM_DL_DB_RECORD_X509_CERTIFICATE:
674 {
675 attributeNameArray = kCertificateAttributeNames;
676 numAttributeNames = kNumCertificateAttributes;
677 break;
678 }
679
680 case CSSM_DL_DB_RECORD_PUBLIC_KEY:
681 case CSSM_DL_DB_RECORD_PRIVATE_KEY:
682 case CSSM_DL_DB_RECORD_SYMMETRIC_KEY:
683 {
684 attributeNameArray = kKeyAttributeNames;
685 numAttributeNames = kNumKeyAttributes;
686 break;
687 }
688
689 default:
690 {
691 CssmError::throwMe (CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED);
692 }
693 }
694
695 // make the attribute array
696 size_t arraySize = numAttributeNames * sizeof (CSSM_DB_ATTRIBUTE_DATA);
697
698 CSSM_DB_ATTRIBUTE_DATA_PTR attributes =
699 (CSSM_DB_ATTRIBUTE_DATA_PTR) allocator ().malloc (arraySize);
700
701 // initialize the array
702 memset (attributes, 0, arraySize);
703 unsigned i;
704 for (i = 0; i < numAttributeNames; ++i)
705 {
706 attributes[i].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER;
707 attributes[i].Info.Label.AttributeID = attributeNameArray[i];
708 }
709
710 // make the attribute record
711 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
712 attrData.DataRecordType = recordType;
713 attrData.SemanticInformation = 0;
714 attrData.NumberOfAttributes = numAttributeNames;
715 attrData.AttributeData = attributes;
716
717 // get the data
718 CssmDataContainer data;
719 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId (db->handle (),
720 recordPtr,
721 &attrData,
722 &data);
723 if (result != 0)
724 {
725 CssmError::throwMe (result);
726 }
727
728 // wrap the data -- write the number of attributes
729 appendUInt32ToData (numAttributeNames, output);
730
731 // for each attribute, write the type and number of values
732 for (i = 0; i < numAttributeNames; ++i)
733 {
734 appendUInt32ToData (attributes[i].Info.AttributeNameFormat, output);
735 appendUInt32ToData (attributes[i].Info.Label.AttributeID, output);
736 appendUInt32ToData (attributes[i].Info.AttributeFormat, output);
737 appendUInt32ToData (attributes[i].NumberOfValues, output);
738
739 // for each value, write the name format, name, length and the data
740 unsigned j;
741 for (j = 0; j < attributes[i].NumberOfValues; ++j)
742 {
743 appendUInt32ToData ((uint32)attributes[i].Value[j].Length, output);
744 if (attributes[i].Value[j].Length != 0)
745 {
746 switch (attributes[i].Info.AttributeFormat)
747 {
748 default:
749 {
750 output.append (CssmPolyData (attributes[i].Value[j]));
751 break;
752 }
753
754 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
755 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
756 {
757 uint32 n = htonl (*(uint32*) attributes[i].Value[j].Data);
758 CSSM_DATA d;
759 d.Length = sizeof (uint32);
760 d.Data = (uint8*) &n;
761 output.append (CssmPolyData (d));
762 break;
763 }
764 }
765 }
766 }
767 }
768
769 // write the length of the data
770 appendUInt32ToData ((uint32)data.Length, output);
771
772 // write the data itself
773 if (data.Length != 0)
774 {
775 output.append (CssmPolyData (data));
776 }
777
778 // clean up
779 for (i = 0; i < numAttributeNames; ++i)
780 {
781 unsigned j;
782 for (j = 0; j < attributes[i].NumberOfValues; ++j)
783 {
784 allocator ().free (attributes[i].Value[j].Data);
785 }
786
787 allocator ().free (attributes[i].Value);
788 }
789
790 allocator ().free (attributes);
791
792 // copy out the data if the caller needs it
793 if (dataBlob)
794 {
795 dataBlob->Data = data.Data;
796 dataBlob->Length = data.Length;
797 data.Data = NULL;
798 data.Length = 0;
799 }
800 }
801
802 void
803 SSDLSession::getUniqueIdForSymmetricKey (SSDatabase &db, CSSM_DATA &label,
804 CSSM_DB_UNIQUE_RECORD_PTR &uniqueRecord)
805 {
806 // set up a query to get the key
807 CSSM_SELECTION_PREDICATE predicate;
808 predicate.DbOperator = CSSM_DB_EQUAL;
809 predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER;
810 predicate.Attribute.Info.Label.AttributeID = kSymmetricKeyLabel;
811 predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
812 predicate.Attribute.NumberOfValues = 1;
813 // the label of the corresponding key is the first 20 bytes of the blob we returned
814 predicate.Attribute.Value = &label;
815
816 CSSM_QUERY query;
817 query.RecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
818 query.Conjunctive = CSSM_DB_NONE;
819 query.NumSelectionPredicates = 1;
820 query.SelectionPredicate = &predicate;
821
822 // fill out the record data
823 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttributeData;
824 recordAttributeData.DataRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
825 recordAttributeData.SemanticInformation = 0;
826 recordAttributeData.NumberOfAttributes = 0;
827 recordAttributeData.AttributeData = NULL;
828
829 // get the data
830 CSSM_HANDLE handle;
831 CSSM_RETURN result = CSSM_DL_DataGetFirst (db->handle (), &query, &handle, &recordAttributeData, NULL,
832 &uniqueRecord);
833 if (result)
834 {
835 CssmError::throwMe (result);
836 }
837
838 // clean up
839 CSSM_DL_DataAbortQuery (db->handle (), handle);
840 }
841
842 void
843 SSDLSession::getCorrespondingSymmetricKey (SSDatabase &db, CSSM_DATA &labelData, CssmDataContainer &data)
844 {
845 // get the unique ID
846 CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord;
847 getUniqueIdForSymmetricKey (db, labelData, uniqueRecord);
848
849 // from this. get the wrapped attributes and data
850 getWrappedAttributesAndData (db, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueRecord, data, NULL);
851
852 // clean up after the query
853 CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord);
854 }
855
856 void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputParams, void **outOutputParams)
857 {
858 CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS* params =
859 (CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams;
860
861 SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID));
862
863 CSSM_DATA *outputData = (CSSM_DATA*) outOutputParams;
864 CssmDataContainer output;
865
866 // get the record type and requested attributes from the DL
867 CssmDataContainer data;
868 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(),
869 uniqueID,
870 params->attributes,
871 NULL);
872
873 if (result)
874 {
875 CssmError::throwMe(result);
876 }
877
878 // get the real data and all of the attributes from the DL
879 CssmDataContainer blobData;
880 getWrappedAttributesAndData (db, params->attributes->DataRecordType, uniqueID, data, &blobData);
881
882 // write out the data blob
883 appendUInt32ToData ((uint32)data.Length, output);
884 output.append (CssmPolyData (data));
885
886 // figure out what we need to do with the key blob
887 CssmDataContainer key;
888 switch (params->attributes->DataRecordType)
889 {
890 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD:
891 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD:
892 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD:
893 {
894 // the label is the first kLabelSize bytes of the resultant data blob
895 CSSM_DATA label = {kLabelSize, blobData.Data};
896
897 // get the key
898 getCorrespondingSymmetricKey (db, label, key);
899 }
900 break;
901
902 default:
903 {
904 break;
905 }
906 }
907
908
909 // write out the length of the key blob
910 appendUInt32ToData ((uint32)key.Length, output);
911
912 if (key.Length != 0)
913 {
914 // write the key
915 output.append (CssmPolyData (key));
916 }
917
918 // copy out the results
919 outputData->Data = output.Data;
920 output.Data = NULL;
921 outputData->Length = output.Length;
922 output.Length = 0;
923 }
924
925 void
926 SSDLSession::cleanupAttributes (uint32 numAttributes, CSSM_DB_ATTRIBUTE_DATA_PTR attributes)
927 {
928 unsigned i;
929 for (i = 0; i < numAttributes; ++i)
930 {
931 unsigned j;
932 for (j = 0; j < attributes[i].NumberOfValues; ++j)
933 {
934 free (attributes[i].Value[j].Data);
935 }
936
937 free (attributes[i].Value);
938 }
939
940 free (attributes);
941 }
942
943 void
944 SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams)
945 {
946 CSSM_RETURN result;
947 CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS* params =
948 (CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams;
949
950 // extract the data for this modify.
951 uint8* finger = params->data->Data;
952 CSSM_DATA data;
953 data.Length = GetUInt32AtFinger (finger);
954 data.Data = finger;
955 if (data.Length + sizeof (UInt32) > params->data->Length)
956 {
957 CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER);
958 }
959
960 // point to the key
961 finger += data.Length;
962
963 // reconstruct the attributes and data
964 uint32 numAttributes;
965 CSSM_DB_ATTRIBUTE_DATA_PTR attributes;
966 CssmDataContainer dataBlob;
967
968 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data);
969
970 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
971 attrData.DataRecordType = params->attributes->DataRecordType;
972 attrData.SemanticInformation = 0;
973 attrData.NumberOfAttributes = numAttributes;
974 attrData.AttributeData = attributes;
975
976 // get the unique ID for this record (from the db's perspective)
977 SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID));
978 CSSM_DB_UNIQUE_RECORD *uniqueIDPtr = uniqueID; // for readability. There's cast overloading
979 // going on here.
980
981 switch (attrData.DataRecordType)
982 {
983 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD:
984 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD:
985 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD:
986 {
987 // read off the data so that we can update the key
988 CssmDataContainer oldData;
989 result = CSSM_DL_DataGetFromUniqueRecordId (db->handle(),
990 uniqueIDPtr,
991 NULL,
992 &oldData);
993 if (result)
994 {
995 CssmError::throwMe (result);
996 }
997
998 CSSM_DB_MODIFY_MODE modifyMode = params->modifyMode;
999
1000 // parse the key data blob
1001 CssmDataContainer keyBlob;
1002 data.Length = GetUInt32AtFinger (finger);
1003 data.Data = finger;
1004
1005 CSSM_DB_RECORD_ATTRIBUTE_DATA* attrDataPtr = NULL;
1006 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
1007
1008 CSSM_DATA labelData = {kLabelSize, oldData.Data};
1009 CSSM_DB_UNIQUE_RECORD_PTR recordID;
1010 getUniqueIdForSymmetricKey (db, labelData, recordID);
1011
1012 CSSM_DB_ATTRIBUTE_DATA_PTR keyAttributes;
1013 uint32 numKeyAttributes;
1014 unwrapAttributesAndData (numKeyAttributes, keyAttributes, keyBlob, data);
1015
1016 // make the attribute data
1017 attrData.DataRecordType = params->recordType;
1018 attrData.SemanticInformation = 0;
1019 attrData.NumberOfAttributes = numKeyAttributes;
1020 attrData.AttributeData = keyAttributes;
1021
1022 attrDataPtr = &attrData;
1023
1024 result = CSSM_DL_DataModify (db->handle(),
1025 CSSM_DL_DB_RECORD_SYMMETRIC_KEY,
1026 recordID,
1027 attrDataPtr,
1028 &keyBlob,
1029 modifyMode);
1030
1031 // clean up
1032 CSSM_DL_FreeUniqueRecord (db->handle (), recordID);
1033
1034 cleanupAttributes (numKeyAttributes, keyAttributes);
1035 break;
1036 }
1037
1038 default:
1039 {
1040 break;
1041 }
1042 }
1043
1044 // save off the new data
1045 result = CSSM_DL_DataModify(db->handle(),
1046 params->recordType,
1047 uniqueIDPtr,
1048 &attrData,
1049 &dataBlob,
1050 params->modifyMode);
1051
1052 // clean up
1053 cleanupAttributes (numAttributes, attributes);
1054
1055 if (result)
1056 {
1057 CssmError::throwMe(result);
1058 }
1059
1060 }
1061
1062 void
1063 SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParams, void** outOutputParams)
1064 {
1065 CSSM_RETURN result;
1066
1067 CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS* params =
1068 (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams;
1069
1070 // extract the data for this insert.
1071 uint8* finger = params->data.Data;
1072 CSSM_DATA data;
1073 data.Length = GetUInt32AtFinger (finger);
1074 data.Data = finger;
1075 finger += data.Length;
1076
1077 // reconstruct the attributes and data
1078 uint32 numAttributes;
1079 CSSM_DB_ATTRIBUTE_DATA_PTR attributes;
1080 CSSM_DATA dataBlob;
1081
1082 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data);
1083
1084 // make the attribute data
1085 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
1086 attrData.DataRecordType = params->recordType;
1087 attrData.SemanticInformation = 0;
1088 attrData.NumberOfAttributes = numAttributes;
1089 attrData.AttributeData = attributes;
1090
1091 // insert into the database
1092 SSUniqueRecord uniqueID (db);
1093 result = CSSM_DL_DataInsert (db->handle(), params->recordType,
1094 &attrData,
1095 &dataBlob,
1096 uniqueID);
1097
1098 // cleanup
1099 allocator ().free (dataBlob.Data);
1100 cleanupAttributes (numAttributes, attributes);
1101
1102 // attach into the CSP/DL mechanism
1103 CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueID);
1104 *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord;
1105
1106 if (result)
1107 {
1108 CssmError::throwMe(result);
1109 }
1110
1111 // Get the key data for this insert
1112 data.Length = GetUInt32AtFinger (finger);
1113 if (data.Length != 0)
1114 {
1115 data.Data = finger;
1116
1117 // parse the key data blob
1118 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data);
1119
1120 // make the attribute data
1121 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
1122 attrData.DataRecordType = params->recordType;
1123 attrData.SemanticInformation = 0;
1124 attrData.NumberOfAttributes = numAttributes;
1125 attrData.AttributeData = attributes;
1126
1127 // insert the key data into the symmetric key table
1128 CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord;
1129 result = CSSM_DL_DataInsert (db->handle(), CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &attrData, &dataBlob,
1130 &uniqueRecord);
1131 if (result)
1132 {
1133 CssmError::throwMe (result);
1134 }
1135
1136 // clean up after inserting the key
1137 CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord);
1138 allocator ().free (dataBlob.Data);
1139 cleanupAttributes (numAttributes, attributes);
1140 }
1141 }
1142
1143 void
1144 SSDLSession::doConvertRecordIdentifier (SSDatabase &db, const void *inInputParams, void **outOutputParams)
1145 {
1146 SSUniqueRecord uniqueId (db);
1147
1148 // clone the unique record
1149 CSSM_DB_UNIQUE_RECORD_PTR clone = (CSSM_DB_UNIQUE_RECORD_PTR) allocator ().malloc (sizeof (CSSM_DB_UNIQUE_RECORD));
1150 *clone = *(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams;
1151
1152 // set the value of the unique record
1153 uniqueId->setUniqueRecordPtr (clone);
1154
1155 // byte swap the retrieved record pointer to host order
1156 uint32* idArray = (uint32*) clone->RecordIdentifier.Data;
1157 idArray[0] = ntohl (idArray[0]);
1158 idArray[1] = ntohl (idArray[1]);
1159 idArray[2] = ntohl (idArray[2]);
1160
1161 CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueId);
1162 *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord;
1163 }
1164
1165 void
1166 SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle,
1167 uint32 inPassThroughId,
1168 const void *inInputParams,
1169 void **outOutputParams)
1170 {
1171 if (inPassThroughId == CSSM_APPLECSPDL_DB_CREATE_WITH_BLOB)
1172 {
1173 CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS* params = (CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS*) inInputParams;
1174 CreateWithBlob(params->dbName, params->dbLocation, *params->dbInfo, params->accessRequest, params->openParameters, *params->blob,
1175 * (CSSM_DB_HANDLE*) outOutputParams);
1176 return;
1177 }
1178
1179 SSDatabase db = findDbHandle(inDbHandle);
1180 switch (inPassThroughId)
1181 {
1182 case CSSM_APPLECSPDL_DB_LOCK:
1183 db->lock();
1184 break;
1185 case CSSM_APPLECSPDL_DB_UNLOCK:
1186 if (inInputParams)
1187 db->unlock(*reinterpret_cast<const CSSM_DATA *>(inInputParams));
1188 else
1189 db->unlock();
1190 break;
1191 case CSSM_APPLECSPDL_DB_STASH:
1192 db->stash();
1193 break;
1194 case CSSM_APPLECSPDL_DB_STASH_CHECK:
1195 db->stashCheck();
1196 break;
1197 case CSSM_APPLECSPDL_DB_GET_SETTINGS:
1198 {
1199 if (!outOutputParams)
1200 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
1201
1202 CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR params =
1203 DatabaseSession::alloc<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS>();
1204 try
1205 {
1206 uint32 idleTimeout;
1207 bool lockOnSleep;
1208 db->getSettings(idleTimeout, lockOnSleep);
1209 params->idleTimeout = idleTimeout;
1210 params->lockOnSleep = lockOnSleep;
1211 }
1212 catch(...)
1213 {
1214 allocator().free(params);
1215 throw;
1216 }
1217 *reinterpret_cast<CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR *>(outOutputParams) = params;
1218 break;
1219 }
1220 case CSSM_APPLECSPDL_DB_SET_SETTINGS:
1221 {
1222 if (!inInputParams)
1223 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER);
1224
1225 const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *params =
1226 reinterpret_cast<const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS *>(inInputParams);
1227 db->setSettings(params->idleTimeout, params->lockOnSleep);
1228 break;
1229 }
1230 case CSSM_APPLECSPDL_DB_IS_LOCKED:
1231 {
1232 if (!outOutputParams)
1233 CssmError::throwMe(CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
1234
1235 CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR params =
1236 DatabaseSession::alloc<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS>();
1237 try
1238 {
1239 params->isLocked = db->isLocked();
1240 }
1241 catch(...)
1242 {
1243 allocator().free(params);
1244 throw;
1245 }
1246 *reinterpret_cast<CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR *>(outOutputParams) = params;
1247 break;
1248 }
1249 case CSSM_APPLECSPDL_DB_CHANGE_PASSWORD:
1250 {
1251 if (!inInputParams)
1252 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER);
1253
1254 const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *params =
1255 reinterpret_cast<const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS *>(inInputParams);
1256 db->changePassphrase(params->accessCredentials);
1257 break;
1258 }
1259 case CSSM_APPLECSPDL_DB_GET_HANDLE:
1260 {
1261 using SecurityServer::DbHandle;
1262 Required(outOutputParams, CSSM_ERRCODE_INVALID_OUTPUT_POINTER);
1263 *reinterpret_cast<CSSM_DL_DB_HANDLE *>(outOutputParams) = db->handle();
1264 break;
1265 }
1266 case CSSM_APPLECSPDL_CSP_RECODE:
1267 {
1268 if (!inInputParams)
1269 CssmError::throwMe(CSSM_ERRCODE_INVALID_INPUT_POINTER);
1270
1271 const CSSM_APPLECSPDL_RECODE_PARAMETERS *params =
1272 reinterpret_cast<const CSSM_APPLECSPDL_RECODE_PARAMETERS *>(inInputParams);
1273
1274 db->recode(CssmData::overlay(params->dbBlob),
1275 CssmData::overlay(params->extraData));
1276 break;
1277 }
1278 case CSSM_APPLECSPDL_DB_GET_RECORD_IDENTIFIER:
1279 {
1280 SSUniqueRecord uniqueID = findSSUniqueRecord(*(CSSM_DB_UNIQUE_RECORD_PTR) inInputParams);
1281 db->getRecordIdentifier(uniqueID, *reinterpret_cast<CSSM_DATA *>(outOutputParams));
1282 break;
1283 }
1284 case CSSM_APPLECSPDL_DB_COPY_BLOB:
1285 {
1286 // make the output parameters
1287 db->copyBlob(*reinterpret_cast<CSSM_DATA *>(outOutputParams));
1288 break;
1289 }
1290 case CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION:
1291 {
1292 doInsertWithoutEncryption (db, inInputParams, outOutputParams);
1293 break;
1294 }
1295 case CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION:
1296 {
1297 doModifyWithoutEncryption (db, inInputParams, outOutputParams);
1298 break;
1299 }
1300 case CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION:
1301 {
1302 doGetWithoutEncryption (db, inInputParams, outOutputParams);
1303 break;
1304 }
1305 case CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER:
1306 {
1307 doConvertRecordIdentifier (db, inInputParams, outOutputParams);
1308 break;
1309 }
1310 default:
1311 {
1312 CSSM_RETURN result = CSSM_DL_PassThrough(db->handle(), inPassThroughId, inInputParams, outOutputParams);
1313 if (result)
1314 CssmError::throwMe(result);
1315 break;
1316 }
1317 }
1318 }
1319
1320 CSSM_DB_HANDLE
1321 SSDLSession::makeDbHandle(SSDatabase &inDb)
1322 {
1323 StLock<Mutex> _(mDbHandleLock);
1324 CSSM_DB_HANDLE aDbHandle = inDb->handle().DBHandle;
1325 bool inserted;
1326 inserted = mDbHandleMap.insert(DbHandleMap::value_type(aDbHandle, inDb)).second;
1327 assert(inserted);
1328 // fprintf(stderr, "%p Added %p to %p\n", pthread_self(), (void*) aDbHandle, (void*) this);
1329 return aDbHandle;
1330 }
1331
1332 SSDatabase
1333 SSDLSession::killDbHandle(CSSM_DB_HANDLE inDbHandle)
1334 {
1335 StLock<Mutex> _(mDbHandleLock);
1336 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle);
1337 if (it == mDbHandleMap.end())
1338 {
1339 // fprintf(stderr, "Can't find %p in %p\n", (void*) inDbHandle, this);
1340 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
1341 }
1342
1343 SSDatabase db = it->second;
1344 // fprintf(stderr, "%p Removed %p from %p\n", pthread_self(), (void*) it->first, (void*) this);
1345 mDbHandleMap.erase(it);
1346 return db;
1347 }
1348
1349 SSDatabase
1350 SSDLSession::findDbHandle(CSSM_DB_HANDLE inDbHandle)
1351 {
1352 StLock<Mutex> _(mDbHandleLock);
1353 // fprintf(stderr, "%p Looking for %p in %p\n", pthread_self(), (void*) inDbHandle, (void*) this);
1354 DbHandleMap::iterator it = mDbHandleMap.find(inDbHandle);
1355 if (it == mDbHandleMap.end())
1356 {
1357 // fprintf(stderr, "%p Can't find %p in %p\n", pthread_self(), (void*) inDbHandle, this);
1358 DbHandleMap::iterator it = mDbHandleMap.begin();
1359 while (it != mDbHandleMap.end())
1360 {
1361 // fprintf(stderr, "\t%p\n", (void*) it->first);
1362 it++;
1363 }
1364
1365 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
1366 }
1367
1368 return it->second;
1369 }
1370
1371 CSSM_DB_UNIQUE_RECORD_PTR
1372 SSDLSession::makeSSUniqueRecord(SSUniqueRecord &uniqueId)
1373 {
1374 StLock<Mutex> _(mSSUniqueRecordLock);
1375 CSSM_HANDLE ref = CSSM_HANDLE(static_cast<CSSM_DB_UNIQUE_RECORD *>(uniqueId));
1376 bool inserted;
1377 inserted = mSSUniqueRecordMap.insert(SSUniqueRecordMap::value_type(ref, uniqueId)).second;
1378 assert(inserted);
1379 return createUniqueRecord(ref);
1380 }
1381
1382 SSUniqueRecord
1383 SSDLSession::killSSUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
1384 {
1385 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord);
1386 StLock<Mutex> _(mSSUniqueRecordLock);
1387 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref);
1388 if (it == mSSUniqueRecordMap.end())
1389 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
1390
1391 SSUniqueRecord uniqueRecord = it->second;
1392 mSSUniqueRecordMap.erase(it);
1393 freeUniqueRecord(inUniqueRecord);
1394 return uniqueRecord;
1395 }
1396
1397 SSUniqueRecord
1398 SSDLSession::findSSUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
1399 {
1400 CSSM_HANDLE ref = parseUniqueRecord(inUniqueRecord);
1401 StLock<Mutex> _(mSSUniqueRecordLock);
1402 SSUniqueRecordMap::iterator it = mSSUniqueRecordMap.find(ref);
1403 if (it == mSSUniqueRecordMap.end())
1404 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
1405
1406 return it->second;
1407 }
1408
1409 CSSM_DB_UNIQUE_RECORD_PTR
1410 SSDLSession::createUniqueRecord(CSSM_HANDLE ref)
1411 {
1412 CSSM_DB_UNIQUE_RECORD *aUniqueRecord = DatabaseSession::alloc<CSSM_DB_UNIQUE_RECORD>();
1413 memset(aUniqueRecord, 0, sizeof(CSSM_DB_UNIQUE_RECORD));
1414 aUniqueRecord->RecordIdentifier.Length = sizeof(CSSM_HANDLE);
1415 try
1416 {
1417 aUniqueRecord->RecordIdentifier.Data = DatabaseSession::alloc<uint8>(sizeof(CSSM_HANDLE));
1418 *reinterpret_cast<CSSM_HANDLE *>(aUniqueRecord->RecordIdentifier.Data) = ref;
1419 }
1420 catch(...)
1421 {
1422 free(aUniqueRecord);
1423 throw;
1424 }
1425
1426 return aUniqueRecord;
1427 }
1428
1429 CSSM_HANDLE
1430 SSDLSession::parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
1431 {
1432 if (inUniqueRecord.RecordIdentifier.Length != sizeof(CSSM_HANDLE))
1433 CssmError::throwMe(CSSMERR_DL_INVALID_RECORD_UID);
1434
1435 return *reinterpret_cast<CSSM_HANDLE *>(inUniqueRecord.RecordIdentifier.Data);
1436 }
1437
1438 void
1439 SSDLSession::freeUniqueRecord(CSSM_DB_UNIQUE_RECORD &inUniqueRecord)
1440 {
1441 if (inUniqueRecord.RecordIdentifier.Length != 0
1442 && inUniqueRecord.RecordIdentifier.Data != NULL)
1443 {
1444 inUniqueRecord.RecordIdentifier.Length = 0;
1445 allocator().free(inUniqueRecord.RecordIdentifier.Data);
1446 }
1447 allocator().free(&inUniqueRecord);
1448 }