]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / libsecurity_apple_cspdl / lib / SSDLSession.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd
A
2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
3 *
b1ab9ed8
A
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.
d8f41ccd 9 *
b1ab9ed8
A
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
29using namespace CssmClient;
30using namespace SecurityServer;
31using namespace std;
32
33//
34// SSDLSession -- Security Server DL session
35//
36SSDLSession::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
60SSDLSession::~SSDLSession()
427c49bc 61try
b1ab9ed8 62{
b1ab9ed8
A
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}
427c49bc
A
74catch (...)
75{
fa7225c8
A
76 // Prevent re-throw of exception.
77 return;
427c49bc 78}
b1ab9ed8
A
79
80// Utility functions
81void
82SSDLSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList)
83{
84 // @@@ Fix client lib
85 CSSM_DL_GetDbNames(mDL->handle(), &outNameList);
86}
87
88
89void
90SSDLSession::FreeNameList(CSSM_NAME_LIST &inNameList)
91{
92 // @@@ Fix client lib
93 CSSM_DL_FreeNameList(mDL->handle(), &inNameList);
94}
95
96
97void
98SSDLSession::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.
108void
109SSDLSession::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);
fa7225c8 122 db->ssCreate(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(),
b1ab9ed8
A
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
130void
131SSDLSession::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);
fa7225c8 144 db->ssCreateWithBlob(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(),
b1ab9ed8
A
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
153void
154SSDLSession::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);
fa7225c8 165 db->ssOpen(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(),
b1ab9ed8
A
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.
173void
174SSDLSession::DbClose(CSSM_DB_HANDLE inDbHandle)
175{
176 killDbHandle(inDbHandle)->close();
177}
178
179void
180SSDLSession::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
195void
196SSDLSession::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
204void
205SSDLSession::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
214void
215SSDLSession::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
226void
227SSDLSession::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
235void
236SSDLSession::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
244void
245SSDLSession::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
254void
255SSDLSession::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
263void
264SSDLSession::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.
fa7225c8 272 SSUniqueRecord uniqueId = db->ssInsert(inRecordType, inAttributes, inData);
b1ab9ed8
A
273 outUniqueId = makeSSUniqueRecord(uniqueId);
274 // @@@ If this is a key do the right thing.
275}
276
277void
278SSDLSession::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
288void
289SSDLSession::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
302CSSM_HANDLE
303SSDLSession::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);
d8f41ccd 356 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
b1ab9ed8
A
357 }
358 }
359
360 outUniqueRecord = makeSSUniqueRecord(uniqueId);
361 return resultsHandle;
362}
363
364bool
365SSDLSession::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);
d8f41ccd 417 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
b1ab9ed8
A
418 }
419 }
420
421 outUniqueRecord = makeSSUniqueRecord(uniqueId);
422
423 return true;
424}
425
426void
427SSDLSession::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
437void
438SSDLSession::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);
d8f41ccd 445
b1ab9ed8
A
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
d8f41ccd 458 CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(),
b1ab9ed8
A
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);
d8f41ccd 479 inoutData->Data = reinterpret_cast<uint8 *>(outKey);
b1ab9ed8
A
480 }
481 }
482}
483
484void
485SSDLSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle,
486 CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
487{
488 killSSUniqueRecord(inUniqueRecordIdentifier);
489}
490
d8f41ccd
A
491#pragma clang diagnostic push
492#pragma clang diagnostic ignored "-Wunused-const-variable"
493
b1ab9ed8
A
494static const uint32 kGenericAttributeNames[] =
495{
496 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce',
497 'gena'
498};
499
500const uint32 kNumGenericAttributes = sizeof (kGenericAttributeNames) / sizeof (uint32);
501
502static 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
508const uint32 kNumApplesharePasswordAttributes = sizeof (kApplesharePasswordNames) / sizeof (uint32);
509
510static 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
516const uint32 kNumInternetPasswordAttributes = sizeof (kInternetPasswordNames) / sizeof (uint32);
517
518const 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
523const uint32 kNumKeyAttributes = sizeof (kKeyAttributeNames) / sizeof (uint32);
524
525const uint32 kCertificateAttributeNames[] =
526{
527 'ctyp', 'cenc', 'labl', 'alis', 'subj', 'issu', 'snbr', 'skid', 'hpky'
528};
529
530const uint32 kNumCertificateAttributes = sizeof (kCertificateAttributeNames) / sizeof (uint32);
531
532const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key
533const unsigned kLabelSize = 20;
534const unsigned kNumSymmetricAttributes = 27; // number of attributes to request
535
d8f41ccd
A
536#pragma clang diagnostic pop
537
b1ab9ed8
A
538static void appendUInt32ToData (const uint32 value, CssmDataContainer &data)
539{
540 data.append (CssmPolyData (uint32 (htonl (value))));
541}
542
543static 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
550void
551SSDLSession::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);
d8f41ccd 559
b1ab9ed8
A
560 // compute the end of the data for sanity checking later
561 uint8* maximum = input.Data + input.Length;
d8f41ccd 562
b1ab9ed8
A
563 // make the attribute array
564 attributes = (CSSM_DB_ATTRIBUTE_DATA*) allocator ().malloc (numAttributes * sizeof (CSSM_DB_ATTRIBUTE_DATA));
d8f41ccd 565
b1ab9ed8
A
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);
d8f41ccd 574
b1ab9ed8
A
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);
d8f41ccd 590
b1ab9ed8
A
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 }
d8f41ccd 599
b1ab9ed8
A
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 }
d8f41ccd 606
b1ab9ed8
A
607 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
608 {
609 uint32* d = (uint32*) attributes[i].Value[j].Data;
427c49bc 610 unsigned long numValues = attributes[i].Value[j].Length / sizeof (UInt32);
b1ab9ed8
A
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 }
d8f41ccd 625
b1ab9ed8
A
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
646void
647SSDLSession::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;
d8f41ccd 656
b1ab9ed8
A
657 switch (recordType)
658 {
659 case CSSM_DL_DB_RECORD_GENERIC_PASSWORD:
660 {
661 attributeNameArray = kGenericAttributeNames;
662 numAttributeNames = kNumGenericAttributes;
663 break;
664 }
d8f41ccd 665
b1ab9ed8
A
666 case CSSM_DL_DB_RECORD_INTERNET_PASSWORD:
667 {
668 attributeNameArray = kInternetPasswordNames;
669 numAttributeNames = kNumInternetPasswordAttributes;
670 break;
671 }
d8f41ccd 672
b1ab9ed8
A
673 case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD:
674 {
675 attributeNameArray = kApplesharePasswordNames;
676 numAttributeNames = kNumApplesharePasswordAttributes;
677 break;
678 }
d8f41ccd 679
b1ab9ed8
A
680 case CSSM_DL_DB_RECORD_X509_CERTIFICATE:
681 {
682 attributeNameArray = kCertificateAttributeNames;
683 numAttributeNames = kNumCertificateAttributes;
684 break;
685 }
d8f41ccd 686
b1ab9ed8
A
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 }
d8f41ccd 701
b1ab9ed8
A
702 // make the attribute array
703 size_t arraySize = numAttributeNames * sizeof (CSSM_DB_ATTRIBUTE_DATA);
d8f41ccd 704
b1ab9ed8
A
705 CSSM_DB_ATTRIBUTE_DATA_PTR attributes =
706 (CSSM_DB_ATTRIBUTE_DATA_PTR) allocator ().malloc (arraySize);
d8f41ccd 707
b1ab9ed8
A
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 }
d8f41ccd 716
b1ab9ed8
A
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;
d8f41ccd 723
b1ab9ed8
A
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 }
d8f41ccd 734
b1ab9ed8
A
735 // wrap the data -- write the number of attributes
736 appendUInt32ToData (numAttributeNames, output);
d8f41ccd 737
b1ab9ed8
A
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);
d8f41ccd 745
b1ab9ed8
A
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 {
427c49bc 750 appendUInt32ToData ((uint32)attributes[i].Value[j].Length, output);
b1ab9ed8
A
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 }
d8f41ccd 760
b1ab9ed8
A
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 }
d8f41ccd 775
b1ab9ed8 776 // write the length of the data
427c49bc 777 appendUInt32ToData ((uint32)data.Length, output);
d8f41ccd 778
b1ab9ed8
A
779 // write the data itself
780 if (data.Length != 0)
781 {
782 output.append (CssmPolyData (data));
783 }
d8f41ccd 784
b1ab9ed8
A
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 }
d8f41ccd 793
b1ab9ed8
A
794 allocator ().free (attributes[i].Value);
795 }
d8f41ccd 796
b1ab9ed8 797 allocator ().free (attributes);
d8f41ccd 798
b1ab9ed8
A
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
809void
810SSDLSession::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;
d8f41ccd 828
b1ab9ed8
A
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;
d8f41ccd 835
b1ab9ed8
A
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
849void
850SSDLSession::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);
d8f41ccd 858
b1ab9ed8
A
859 // clean up after the query
860 CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord);
861}
862
863void 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;
d8f41ccd 867
b1ab9ed8 868 SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID));
d8f41ccd 869
b1ab9ed8
A
870 CSSM_DATA *outputData = (CSSM_DATA*) outOutputParams;
871 CssmDataContainer output;
d8f41ccd 872
b1ab9ed8
A
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);
d8f41ccd 879
b1ab9ed8
A
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);
d8f41ccd 888
b1ab9ed8 889 // write out the data blob
427c49bc 890 appendUInt32ToData ((uint32)data.Length, output);
b1ab9ed8 891 output.append (CssmPolyData (data));
d8f41ccd 892
b1ab9ed8
A
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;
d8f41ccd 908
b1ab9ed8
A
909 default:
910 {
911 break;
912 }
913 }
d8f41ccd
A
914
915
b1ab9ed8 916 // write out the length of the key blob
427c49bc 917 appendUInt32ToData ((uint32)key.Length, output);
b1ab9ed8
A
918
919 if (key.Length != 0)
920 {
921 // write the key
922 output.append (CssmPolyData (key));
923 }
d8f41ccd 924
b1ab9ed8
A
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
932void
933SSDLSession::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 }
d8f41ccd 943
b1ab9ed8
A
944 free (attributes[i].Value);
945 }
d8f41ccd 946
b1ab9ed8
A
947 free (attributes);
948}
949
950void
951SSDLSession::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;
d8f41ccd 956
b1ab9ed8
A
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 }
d8f41ccd 966
b1ab9ed8
A
967 // point to the key
968 finger += data.Length;
d8f41ccd 969
b1ab9ed8
A
970 // reconstruct the attributes and data
971 uint32 numAttributes;
972 CSSM_DB_ATTRIBUTE_DATA_PTR attributes;
973 CssmDataContainer dataBlob;
d8f41ccd 974
b1ab9ed8 975 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data);
d8f41ccd 976
b1ab9ed8
A
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;
d8f41ccd 982
b1ab9ed8
A
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.
d8f41ccd 987
b1ab9ed8
A
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 }
d8f41ccd 1004
b1ab9ed8
A
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;
d8f41ccd 1011
b1ab9ed8
A
1012 CSSM_DB_RECORD_ATTRIBUTE_DATA* attrDataPtr = NULL;
1013 CSSM_DB_RECORD_ATTRIBUTE_DATA attrData;
d8f41ccd 1014
b1ab9ed8
A
1015 CSSM_DATA labelData = {kLabelSize, oldData.Data};
1016 CSSM_DB_UNIQUE_RECORD_PTR recordID;
1017 getUniqueIdForSymmetricKey (db, labelData, recordID);
d8f41ccd 1018
b1ab9ed8
A
1019 CSSM_DB_ATTRIBUTE_DATA_PTR keyAttributes;
1020 uint32 numKeyAttributes;
1021 unwrapAttributesAndData (numKeyAttributes, keyAttributes, keyBlob, data);
d8f41ccd 1022
b1ab9ed8
A
1023 // make the attribute data
1024 attrData.DataRecordType = params->recordType;
1025 attrData.SemanticInformation = 0;
1026 attrData.NumberOfAttributes = numKeyAttributes;
1027 attrData.AttributeData = keyAttributes;
d8f41ccd 1028
b1ab9ed8 1029 attrDataPtr = &attrData;
d8f41ccd 1030
b1ab9ed8
A
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);
d8f41ccd 1040
b1ab9ed8
A
1041 cleanupAttributes (numKeyAttributes, keyAttributes);
1042 break;
1043 }
d8f41ccd 1044
b1ab9ed8
A
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);
d8f41ccd 1061
b1ab9ed8
A
1062 if (result)
1063 {
1064 CssmError::throwMe(result);
1065 }
1066
1067}
1068
1069void
1070SSDLSession::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;
d8f41ccd 1076
b1ab9ed8
A
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;
d8f41ccd 1083
b1ab9ed8
A
1084 // reconstruct the attributes and data
1085 uint32 numAttributes;
1086 CSSM_DB_ATTRIBUTE_DATA_PTR attributes;
1087 CSSM_DATA dataBlob;
d8f41ccd 1088
b1ab9ed8 1089 unwrapAttributesAndData (numAttributes, attributes, dataBlob, data);
d8f41ccd 1090
b1ab9ed8
A
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;
d8f41ccd 1097
b1ab9ed8
A
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;
d8f41ccd 1112
b1ab9ed8
A
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);
d8f41ccd 1126
b1ab9ed8
A
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 }
d8f41ccd 1142
b1ab9ed8
A
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
1150void
1151SSDLSession::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);
d8f41ccd 1161
b1ab9ed8
A
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]);
d8f41ccd 1167
b1ab9ed8
A
1168 CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueId);
1169 *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord;
1170}
1171
1172void
1173SSDLSession::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 }
d8f41ccd 1185
b1ab9ed8
A
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;
427c49bc
A
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:
b1ab9ed8
A
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);
d8f41ccd 1280
b1ab9ed8
A
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
fa7225c8 1294 db->ssCopyBlob(*reinterpret_cast<CSSM_DATA *>(outOutputParams));
b1ab9ed8
A
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 }
e3d460c9
A
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 }
fa7225c8
A
1327 case CSSM_APPLECSPDL_DB_RECODE_FINISHED:
1328 {
1329 db->recodeFinished();
1330 break;
1331 }
e3d460c9
A
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;
fa7225c8
A
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;
e3d460c9 1362 }
b1ab9ed8
A
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
1373CSSM_DB_HANDLE
1374SSDLSession::makeDbHandle(SSDatabase &inDb)
1375{
1376 StLock<Mutex> _(mDbHandleLock);
1377 CSSM_DB_HANDLE aDbHandle = inDb->handle().DBHandle;
427c49bc
A
1378 bool inserted;
1379 inserted = mDbHandleMap.insert(DbHandleMap::value_type(aDbHandle, inDb)).second;
b1ab9ed8
A
1380 assert(inserted);
1381 // fprintf(stderr, "%p Added %p to %p\n", pthread_self(), (void*) aDbHandle, (void*) this);
1382 return aDbHandle;
1383}
1384
1385SSDatabase
1386SSDLSession::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 }
d8f41ccd 1395
b1ab9ed8
A
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
1402SSDatabase
1403SSDLSession::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 }
d8f41ccd 1417
b1ab9ed8
A
1418 CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE);
1419 }
1420
1421 return it->second;
1422}
1423
1424CSSM_DB_UNIQUE_RECORD_PTR
1425SSDLSession::makeSSUniqueRecord(SSUniqueRecord &uniqueId)
1426{
1427 StLock<Mutex> _(mSSUniqueRecordLock);
1428 CSSM_HANDLE ref = CSSM_HANDLE(static_cast<CSSM_DB_UNIQUE_RECORD *>(uniqueId));
427c49bc
A
1429 bool inserted;
1430 inserted = mSSUniqueRecordMap.insert(SSUniqueRecordMap::value_type(ref, uniqueId)).second;
b1ab9ed8
A
1431 assert(inserted);
1432 return createUniqueRecord(ref);
1433}
1434
1435SSUniqueRecord
1436SSDLSession::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
1450SSUniqueRecord
1451SSDLSession::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
1462CSSM_DB_UNIQUE_RECORD_PTR
1463SSDLSession::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
1482CSSM_HANDLE
1483SSDLSession::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
1491void
1492SSDLSession::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}