1/*
2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// DatabaseSession.cpp - DL Session.
21//
22#include <security_cdsa_plugin/DatabaseSession.h>
23
24#include <security_cdsa_plugin/Database.h>
25#include <security_cdsa_plugin/DbContext.h>
26#include <security_cdsa_utilities/cssmbridge.h>
27#include <memory>
28#include <security_utilities/debugging.h>
29
30/* log open/close events */
31#define DOCDebug(args...)	secdebug("DBOpen", ## args)
32
33
34using namespace std;
35
36extern "C" char* cssmErrorString(CSSM_RETURN errCode);
37
38//
39// Session constructor
40//
41DatabaseSession::DatabaseSession(DatabaseManager &inDatabaseManager)
42: mDatabaseManager(inDatabaseManager)
43{
44}
45
46DatabaseSession::~DatabaseSession()
47{
48}
49
50
51// Utility functions
52void
53DatabaseSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList)
54{
55	secdebug("dbsession", "GetDbNames");
56	outNameList = mDatabaseManager.getDbNames (*this);
57
58#ifndef NDEBUG
59	// dump the returned names
60	uint32 n;
61	secdebug("dbsession", "GetDbNames returned %d names", outNameList->NumStrings);
62	for (n = 0; n < outNameList->NumStrings; ++n)
63	{
64		secdebug("dbsession", "%d: %s", n, outNameList->String[n]);
65	}
66#endif
67
68	secdebug("dbsession", "********************");
69}
70
71
72void
73DatabaseSession::FreeNameList(CSSM_NAME_LIST &inNameList)
74{
75	secdebug("dbsession", "FreeNameList");
76	mDatabaseManager.freeNameList (*this, inNameList);
77	secdebug("dbsession", "********************");
78}
79
80
81void
82DatabaseSession::DbDelete(const char *inDbName,
83                          const CSSM_NET_ADDRESS *inDbLocation,
84                          const AccessCredentials *inAccessCred)
85{
86    // The databaseManager will notify all its DbContext instances
87    // that the database is question is being deleted.
88	secdebug("dbsession", "DbDelete of %s", inDbName);
89    mDatabaseManager.dbDelete(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), inAccessCred);
90	secdebug("dbsession", "********************");
91}
92
93// DbContext creation and destruction.
94void
95DatabaseSession::DbCreate(const char *inDbName,
96                          const CSSM_NET_ADDRESS *inDbLocation,
97                          const CSSM_DBINFO &inDBInfo,
98                          CSSM_DB_ACCESS_TYPE inAccessRequest,
99                          const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
100                          const void *inOpenParameters,
101                          CSSM_DB_HANDLE &outDbHandle)
102{
103	outDbHandle = CSSM_INVALID_HANDLE;	// CDSA 2.0 says to set this if we fail
104	secdebug("dbsession", "DbCreate of %s", inDbName);
105
106    outDbHandle = insertDbContext(mDatabaseManager.dbCreate(*this,
107                                                            DbName(inDbName, CssmNetAddress::optional(inDbLocation)),
108                                                            inDBInfo,
109                                                            inAccessRequest,
110                                                            inCredAndAclEntry,
111                                                            inOpenParameters));
112	secdebug("dbsession", "DbCreate returned handle %#lx", outDbHandle);
113
114	secdebug("dbsession", "********************");
115}
116
117void
118DatabaseSession::DbOpen(const char *inDbName,
119                        const CSSM_NET_ADDRESS *inDbLocation,
120                        CSSM_DB_ACCESS_TYPE inAccessRequest,
121                        const AccessCredentials *inAccessCred,
122                        const void *inOpenParameters,
123                        CSSM_DB_HANDLE &outDbHandle)
124{
125	DOCDebug("DatabaseSession::DbOpen: dbName %s", inDbName);
126	secdebug("dbsession", "DbOpen of %s", inDbName);
127	outDbHandle = CSSM_INVALID_HANDLE;	// CDSA 2.0 says to set this if we fail
128    outDbHandle = insertDbContext(mDatabaseManager.dbOpen(*this,
129                                                          DbName(inDbName, CssmNetAddress::optional(inDbLocation)),
130                                                          inAccessRequest,
131                                                          inAccessCred,
132                                                          inOpenParameters));
133	secdebug("dbsession", "DbOpen returned handle %#lx", outDbHandle);
134	secdebug("dbsession", "********************");
135}
136
137CSSM_DB_HANDLE
138DatabaseSession::insertDbContext(DbContext &inDbContext)
139{
140    CSSM_DB_HANDLE aDbHandle;
141    try
142    {
143        aDbHandle = inDbContext.handle ();
144        StLock<Mutex> _(mDbContextMapLock);
145        mDbContextMap.insert(DbContextMap::value_type(aDbHandle, &inDbContext));
146    }
147    catch (...)
148    {
149        // Close the context
150        mDatabaseManager.dbClose(inDbContext);
151        throw;
152    }
153
154    return aDbHandle;
155}
156
157DbContext &
158DatabaseSession::findDbContext(CSSM_DB_HANDLE inDbHandle)
159{
160    StLock<Mutex> _(mDbContextMapLock);
161    DbContextMap::iterator it = mDbContextMap.find(inDbHandle);
162    if (it == mDbContextMap.end())
163        CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE);
164    return *it->second;
165}
166
167void
168DatabaseSession::closeAll()
169{
170    StLock<Mutex> _(mDbContextMapLock);
171    for (DbContextMap::iterator it = mDbContextMap.begin();
172         it != mDbContextMap.end();
173         it++)
174    {
175        DbContext *aDbContext = it->second;
176        try
177        {
178            mDatabaseManager.dbClose(*aDbContext);
179            // This is done by the database itself which owns the context.
180            //delete aDbContext;
181        }
182        catch (...)
183        {
184            // Ignore exceptions since we want to close as many DBs as possible.
185            // XXX @@@ log an error or something.
186        }
187    }
188
189    mDbContextMap.clear();
190	secdebug("dbsession", "********************");
191}
192
193// Operations using DbContext instances.
194void
195DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle)
196{
197    StLock<Mutex> _(mDbContextMapLock);
198	DOCDebug("DatabaseSession::Close");
199	secdebug("dbsession", "DbClose of handle %ld", inDbHandle);
200    DbContextMap::iterator it = mDbContextMap.find(inDbHandle);
201    if (it == mDbContextMap.end())
202        CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE);
203    auto_ptr<DbContext> aDbContext(it->second);
204    mDbContextMap.erase(it);
205    mDatabaseManager.dbClose(*aDbContext);
206	secdebug("dbsession", "********************");
207}
208
209void
210DatabaseSession::CreateRelation(CSSM_DB_HANDLE inDbHandle,
211                                CSSM_DB_RECORDTYPE inRelationID,
212                                const char *inRelationName,
213                                uint32 inNumberOfAttributes,
214                                const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo,
215                                uint32 inNumberOfIndexes,
216                                const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo)
217{
218	secdebug("dbsession", "CreateRelation from handle %ld of record type %X with relation name %s", inDbHandle, inRelationID, inRelationName);
219	secdebug("dbsession", "number of attributes = %d", inNumberOfAttributes);
220#ifndef NDEBUG
221	unsigned n;
222	for (n = 0; n < inNumberOfAttributes; ++n)
223	{
224		secdebug("dbsession", "%d: id %d name %s, data type %d", n, inAttributeInfo[n].AttributeId,
225																	inAttributeInfo[n].AttributeName,
226																	inAttributeInfo[n].DataType);
227	}
228#endif
229
230	secdebug("dbsession", "number of indexes: %d", inNumberOfIndexes);
231#ifndef NDEBUG
232	for (n = 0; n < inNumberOfIndexes; ++n)
233	{
234		secdebug("dbsession", "%d: id %d indexid %d indextype %d location %d", n, inIndexInfo.AttributeId,
235																				  inIndexInfo.IndexedDataLocation,
236																				  inIndexInfo.IndexId,
237																				  inIndexInfo.IndexType);
238	}
239#endif
240
241    DbContext &aDbContext = findDbContext(inDbHandle);
242    return aDbContext.mDatabase.createRelation(aDbContext, inRelationID, inRelationName,
243                                                inNumberOfAttributes, inAttributeInfo,
244                                                inNumberOfIndexes, inIndexInfo);
245	secdebug("dbsession", "********************");
246}
247
248void
249DatabaseSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle,
250                                 CSSM_DB_RECORDTYPE inRelationID)
251{
252	secdebug("dbsession", "DestroyRelation (handle %ld) %d", inDbHandle, inRelationID);
253    DbContext &aDbContext = findDbContext(inDbHandle);
254    aDbContext.mDatabase.destroyRelation(aDbContext, inRelationID);
255	secdebug("dbsession", "********************");
256}
257
258void
259DatabaseSession::Authenticate(CSSM_DB_HANDLE inDbHandle,
260                              CSSM_DB_ACCESS_TYPE inAccessRequest,
261                              const AccessCredentials &inAccessCred)
262{
263	secdebug("dbsession", "Authenticate (handle %ld) inAccessRequest %d", inDbHandle, inAccessRequest);
264    DbContext &aDbContext = findDbContext(inDbHandle);
265    aDbContext.mDatabase.authenticate(aDbContext, inAccessRequest, inAccessCred);
266	secdebug("dbsession", "********************");
267}
268
269
270void
271DatabaseSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle,
272                          const CSSM_STRING *inSelectionTag,
273                          uint32 &outNumberOfAclInfos,
274                          CSSM_ACL_ENTRY_INFO_PTR &outAclInfos)
275{
276	secdebug("dbsession", "GetDbAcl (handle %ld)", inDbHandle);
277    DbContext &aDbContext = findDbContext(inDbHandle);
278    aDbContext.mDatabase.getDbAcl(aDbContext, inSelectionTag, outNumberOfAclInfos, outAclInfos);
279	secdebug("dbsession", "********************");
280}
281
282void
283DatabaseSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle,
284                             const AccessCredentials &inAccessCred,
285                             const CSSM_ACL_EDIT &inAclEdit)
286{
287	secdebug("dbsession", "ChangeDbAcl (handle %ld)", inDbHandle);
288    DbContext &aDbContext = findDbContext(inDbHandle);
289    aDbContext.mDatabase.changeDbAcl(aDbContext, inAccessCred, inAclEdit);
290	secdebug("dbsession", "********************");
291}
292
293void
294DatabaseSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle,
295                            CSSM_ACL_OWNER_PROTOTYPE &outOwner)
296{
297	secdebug("dbsession", "GetDbOwner (handle %ld)", inDbHandle);
298    DbContext &aDbContext = findDbContext(inDbHandle);
299    aDbContext.mDatabase.getDbOwner(aDbContext, outOwner);
300	secdebug("dbsession", "********************");
301}
302
303void
304DatabaseSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle,
305                               const AccessCredentials &inAccessCred,
306                               const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner)
307{
308	secdebug("dbsession", "ChangeDbOwner (handle %ld)", inDbHandle);
309    DbContext &aDbContext = findDbContext(inDbHandle);
310    aDbContext.mDatabase.changeDbOwner(aDbContext, inAccessCred, inNewOwner);
311	secdebug("dbsession", "********************");
312}
313
314void
315DatabaseSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle,
316                                     char **outDbName)
317{
318	secdebug("dbsession", "GetDbNameFromHandle (handle %ld)", inDbHandle);
319    DbContext &aDbContext = findDbContext(inDbHandle);
320    Required(outDbName) = aDbContext.mDatabase.getDbNameFromHandle(aDbContext);
321	secdebug("dbsession", "name: %s", *outDbName);
322	secdebug("dbsession", "********************");
323}
324
325
326#ifndef NDEBUG
327
328#if 0 /* unusued functions */
329
330static
331void DumpAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &info)
332{
333	const char* attrNameType;
334	switch (info.AttributeFormat)
335	{
336		case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
337			attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_STRING";
338			break;
339
340		case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
341			attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_OID";
342			break;
343
344		case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
345			attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER";
346			break;
347	}
348
349	secdebug("dbsession", "  Attribute name type: %s", attrNameType);
350	switch (info.AttributeFormat)
351	{
352		case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
353			secdebug("dbsession", "  name: %s", info.Label.AttributeName);
354			break;
355
356		case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
357			secdebug("dbsession", "  name: %d", info.Label.AttributeID);
358			break;
359
360		case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
361			secdebug("dbsession", "  name is oid");
362			break;
363	}
364
365	const char* s;
366	switch (info.AttributeFormat)
367	{
368		case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
369			s = "CSSM_DB_ATTRIBUTE_FORMAT_STRING";
370			break;
371		case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
372			s = "CSSM_DB_ATTRIBUTE_FORMAT_SINT32";
373			break;
374		case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
375			s = "CSSM_DB_ATTRIBUTE_FORMAT_UINT32";
376			break;
377		case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
378			s = "CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM";
379			break;
380		case CSSM_DB_ATTRIBUTE_FORMAT_REAL:
381			s = "CSSM_DB_ATTRIBUTE_FORMAT_REAL";
382			break;
383		case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
384			s = "CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE";
385			break;
386		case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
387			s = "CSSM_DB_ATTRIBUTE_FORMAT_BLOB";
388			break;
389		case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
390			s = "CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32";
391			break;
392		case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX:
393			s = "CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX";
394			break;
395	}
396
397	secdebug("dbsession", "  attribute format: %s", s);
398}
399
400
401static
402void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes)
403{
404	if (!inAttributes)
405	{
406		secdebug("dbsession", "No attributes defined.");
407		return;
408	}
409
410	secdebug("dbsession", "insert into %d", inAttributes->DataRecordType);
411	secdebug("dbsession", "Semantic information %d", inAttributes->SemanticInformation);
412	secdebug("dbsession", "Number of attributes: %d", inAttributes->NumberOfAttributes);
413
414	unsigned n;
415	for (n = 0; n < inAttributes->NumberOfAttributes; ++n)
416	{
417		DumpAttributeInfo(inAttributes->AttributeData[n].Info);
418		secdebug("dbsession", "Attribute %d\n", n);
419		secdebug("dbsession", "  number of values: %d", inAttributes->AttributeData[n].NumberOfValues);
420		unsigned i;
421		for (i = 0; i < inAttributes->AttributeData[n].NumberOfValues; ++i)
422		{
423			switch (inAttributes->AttributeData[n].Info.AttributeFormat)
424			{
425				case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
426				{
427					std::string ss((char*) inAttributes->AttributeData[n].Value[i].Data, inAttributes->AttributeData[n].Value[i].Length);
428					secdebug("dbsession", "    Value %d: %s", i, ss.c_str());
429					break;
430				}
431				case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
432					secdebug("dbsession", "    Value %d: %d", i, *(sint32*)inAttributes->AttributeData[n].Value[i].Data);
433					break;
434				case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
435					secdebug("dbsession", "    Value %d: %u", i, *(uint32*)inAttributes->AttributeData[n].Value[i].Data);
436					break;
437				case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
438					secdebug("dbsession", "    Value %d: (bignum)", i);
439					break;
440				case CSSM_DB_ATTRIBUTE_FORMAT_REAL:
441					secdebug("dbsession", "    Value %d: %f", i, *(double*)inAttributes->AttributeData[n].Value[i].Data);
442					break;
443				case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
444					secdebug("dbsession", "    Value %d: %s", i, (char*)inAttributes->AttributeData[n].Value[i].Data);
445					break;
446				case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
447					secdebug("dbsession", "    Value %d: (blob)", i);
448					break;
449				case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
450				{
451					unsigned long j;
452					unsigned long numInts = inAttributes->AttributeData[n].Value[i].Length / sizeof(UInt32);
453					for (j = 0; j < numInts; ++j)
454					{
455						uint32* nums = (uint32*) inAttributes->AttributeData[n].Value[i].Data;
456						secdebug("dbsession", "      %d", nums[j]);
457					}
458
459					break;
460				}
461
462				case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX:
463					secdebug("dbsession", "    Value %d: (complex)", i);
464					break;
465			}
466		}
467	}
468}
469#endif
470
471
472static void
473DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record)
474{
475/*
476	const char* s;
477
478	switch (record.RecordLocator.IndexType)
479	{
480		case CSSM_DB_INDEX_UNIQUE:
481		{
482			s = "CSSM_DB_INDEX_UNIQUE";
483			break;
484		}
485
486		case CSSM_DB_INDEX_NONUNIQUE:
487		{
488			s = "CSSM_DB_INDEX_NONUNIQUE";
489			break;
490		}
491	}
492
493	secdebug("dbsession", "RecordLocator.IndexType: %s", s);
494
495	switch (record.RecordLocator.IndexedDataLocation)
496	{
497		case CSSM_DB_INDEX_ON_UNKNOWN:
498		{
499			s = "CSSM_DB_INDEX_ON_UNKNOWN";
500			break;
501		}
502
503		case CSSM_DB_INDEX_ON_ATTRIBUTE:
504		{
505			s = "CSSM_DB_INDEX_ON_ATTRIBUTE";
506			break;
507		}
508
509		case CSSM_DB_INDEX_ON_RECORD:
510		{
511			s = "CSSM_DB_INDEX_ON_RECORD";
512			break;
513		}
514	}
515
516	secdebug("dbsession", "RecordLocator.IndexedDataLocation: %s", s);
517
518	secdebug("dbsession", "Attribute info:");
519
520	DumpAttributeInfo(record.RecordLocator.Info);
521*/
522
523	// put the record ID into hex
524	std::string output;
525	char hexBuffer[4];
526	unsigned i;
527	for (i = 0; i < record.RecordIdentifier.Length; ++i)
528	{
529		sprintf(hexBuffer, "%02X", record.RecordIdentifier.Data[i]);
530		output += hexBuffer;
531	}
532
533	secdebug("dbsession", "    RecordIdentifier.Data: %s", output.c_str());
534}
535#endif /* NDEBUG */
536
537void
538DatabaseSession::DataInsert(CSSM_DB_HANDLE inDbHandle,
539                            CSSM_DB_RECORDTYPE inRecordType,
540                            const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
541                            const CssmData *inData,
542                            CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId)
543{
544	secdebug("dbsession", "%p DataInsert(%lx,%x)", this, inDbHandle, inRecordType);
545    DbContext &aDbContext = findDbContext(inDbHandle);
546    outUniqueId = aDbContext.mDatabase.dataInsert(aDbContext, inRecordType, inAttributes, inData);
547
548#ifndef NDEBUG
549	secdebug("dbsession", "Returned unique id:");
550	DumpUniqueRecord(*outUniqueId);
551#endif
552
553	secdebug("dbsession", "********************");
554}
555
556
557void
558DatabaseSession::DataDelete(CSSM_DB_HANDLE inDbHandle,
559                            const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
560{
561	secdebug("dbsession", "%p DataDelete(%lx)", this, inDbHandle);
562    DbContext &aDbContext = findDbContext(inDbHandle);
563    aDbContext.mDatabase.dataDelete(aDbContext, inUniqueRecordIdentifier);
564
565#ifndef NDEBUG
566	secdebug("dbsession", "Record identifier:");
567	DumpUniqueRecord(inUniqueRecordIdentifier);
568#endif
569	secdebug("dbsession", "********************");
570}
571
572
573void
574DatabaseSession::DataModify(CSSM_DB_HANDLE inDbHandle,
575                            CSSM_DB_RECORDTYPE inRecordType,
576                            CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier,
577                            const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified,
578                            const CssmData *inDataToBeModified,
579                            CSSM_DB_MODIFY_MODE inModifyMode)
580{
581	secdebug("dbsession", "%p DataModify(%lx,%x)", this, inDbHandle, inRecordType);
582    DbContext &aDbContext = findDbContext(inDbHandle);
583    aDbContext.mDatabase.dataModify(aDbContext, inRecordType, inoutUniqueRecordIdentifier,
584                                     inAttributesToBeModified, inDataToBeModified, inModifyMode);
585#ifndef NDEBUG
586	secdebug("dbsession", "Out record identifier:");
587	DumpUniqueRecord(inoutUniqueRecordIdentifier);
588#endif
589	secdebug("dbsession", "********************");
590}
591
592CSSM_HANDLE
593DatabaseSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle,
594                              const CssmQuery *inQuery,
595                              CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
596                              CssmData *inoutData,
597                              CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId)
598{
599	secdebug("dbsession", "%p DataGetFirst(%lx)", this, inDbHandle);
600    DbContext &aDbContext = findDbContext(inDbHandle);
601
602	CSSM_HANDLE result = aDbContext.mDatabase.dataGetFirst(aDbContext, inQuery,
603														   inoutAttributes, inoutData, outUniqueId);
604#ifndef NDEBUG
605	secdebug("dbsession", "result handle: %lx", result);
606	if (result != 0)
607	{
608		secdebug("dbsession", "Returned ID:");
609		DumpUniqueRecord(*outUniqueId);
610	}
611#endif
612
613	secdebug("dbsession", "********************");
614	return result;
615}
616
617bool
618DatabaseSession::DataGetNext(CSSM_DB_HANDLE inDbHandle,
619                             CSSM_HANDLE inResultsHandle,
620                             CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
621                             CssmData *inoutData,
622                             CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord)
623{
624	secdebug("dbsession", "DataGetNext(%lx)", inDbHandle);
625    DbContext &aDbContext = findDbContext(inDbHandle);
626
627	bool result = aDbContext.mDatabase.dataGetNext(aDbContext, inResultsHandle, inoutAttributes,
628			inoutData, outUniqueRecord);
629
630#ifndef NDEBUG
631	if (result)
632	{
633		secdebug("dbsession", "Returned ID:");
634		DumpUniqueRecord(*outUniqueRecord);
635	}
636#endif
637
638	secdebug("dbsession", "********************");
639	return result;
640}
641
642void
643DatabaseSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle,
644                                CSSM_HANDLE inResultsHandle)
645{
646	secdebug("dbsession", "%p DataAbortQuery(%lx)", this, inDbHandle);
647    DbContext &aDbContext = findDbContext(inDbHandle);
648    aDbContext.mDatabase.dataAbortQuery(aDbContext, inResultsHandle);
649	secdebug("dbsession", "********************");
650}
651
652void
653DatabaseSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle,
654                                           const CSSM_DB_UNIQUE_RECORD &inUniqueRecord,
655                                           CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
656                                           CssmData *inoutData)
657{
658	secdebug("dbsession", "%p DataGetFromUniqueId(%lx)", this, inDbHandle);
659#ifndef NDEBUG
660	secdebug("dbsession", "inUniqueRecord:");
661	DumpUniqueRecord(inUniqueRecord);
662#endif
663
664    DbContext &aDbContext = findDbContext(inDbHandle);
665    aDbContext.mDatabase.dataGetFromUniqueRecordId(aDbContext, inUniqueRecord,
666                                                   inoutAttributes, inoutData);
667	secdebug("dbsession", "********************");
668}
669
670void
671DatabaseSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle,
672                                  CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
673{
674	secdebug("dbsession", "FreeUniqueRecord: %lx", inDbHandle);
675#ifndef NDEBUG
676	secdebug("dbsession", "inUniqueRecordIdentifier follows:");
677	DumpUniqueRecord(inUniqueRecordIdentifier);
678#endif
679    DbContext &aDbContext = findDbContext(inDbHandle);
680    aDbContext.mDatabase.freeUniqueRecord(aDbContext, inUniqueRecordIdentifier);
681	secdebug("dbsession", "********************");
682}
683
684void
685DatabaseSession::PassThrough(CSSM_DB_HANDLE inDbHandle,
686                             uint32 passThroughId,
687                             const void *inputParams,
688                             void **outputParams)
689{
690	DbContext &aDbContext = findDbContext(inDbHandle);
691	aDbContext.mDatabase.passThrough(aDbContext, passThroughId, inputParams, outputParams);
692}
693