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