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