DatabaseSession.cpp [plain text]
#include <security_cdsa_plugin/DatabaseSession.h>
#include <security_cdsa_plugin/Database.h>
#include <security_cdsa_plugin/DbContext.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <memory>
#include <security_utilities/debugging.h>
#define DOCDebug(args...) secdebug("DBOpen", ## args)
using namespace std;
extern "C" char* cssmErrorString(CSSM_RETURN errCode);
DatabaseSession::DatabaseSession(DatabaseManager &inDatabaseManager)
: mDatabaseManager(inDatabaseManager)
{
}
DatabaseSession::~DatabaseSession()
{
}
void
DatabaseSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList)
{
secdebug("dbsession", "GetDbNames");
outNameList = mDatabaseManager.getDbNames (*this);
#ifndef NDEBUG
uint32 n;
secdebug("dbsession", "GetDbNames returned %d names", outNameList->NumStrings);
for (n = 0; n < outNameList->NumStrings; ++n)
{
secdebug("dbsession", "%d: %s", n, outNameList->String[n]);
}
#endif
secdebug("dbsession", "********************");
}
void
DatabaseSession::FreeNameList(CSSM_NAME_LIST &inNameList)
{
secdebug("dbsession", "FreeNameList");
mDatabaseManager.freeNameList (*this, inNameList);
secdebug("dbsession", "********************");
}
void
DatabaseSession::DbDelete(const char *inDbName,
const CSSM_NET_ADDRESS *inDbLocation,
const AccessCredentials *inAccessCred)
{
secdebug("dbsession", "DbDelete of %s", inDbName);
mDatabaseManager.dbDelete(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), inAccessCred);
secdebug("dbsession", "********************");
}
void
DatabaseSession::DbCreate(const char *inDbName,
const CSSM_NET_ADDRESS *inDbLocation,
const CSSM_DBINFO &inDBInfo,
CSSM_DB_ACCESS_TYPE inAccessRequest,
const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
const void *inOpenParameters,
CSSM_DB_HANDLE &outDbHandle)
{
outDbHandle = CSSM_INVALID_HANDLE; secdebug("dbsession", "DbCreate of %s", inDbName);
outDbHandle = insertDbContext(mDatabaseManager.dbCreate(*this,
DbName(inDbName, CssmNetAddress::optional(inDbLocation)),
inDBInfo,
inAccessRequest,
inCredAndAclEntry,
inOpenParameters));
secdebug("dbsession", "DbCreate returned handle %#lx", outDbHandle);
secdebug("dbsession", "********************");
}
void
DatabaseSession::DbOpen(const char *inDbName,
const CSSM_NET_ADDRESS *inDbLocation,
CSSM_DB_ACCESS_TYPE inAccessRequest,
const AccessCredentials *inAccessCred,
const void *inOpenParameters,
CSSM_DB_HANDLE &outDbHandle)
{
DOCDebug("DatabaseSession::DbOpen: dbName %s", inDbName);
secdebug("dbsession", "DbOpen of %s", inDbName);
outDbHandle = CSSM_INVALID_HANDLE; outDbHandle = insertDbContext(mDatabaseManager.dbOpen(*this,
DbName(inDbName, CssmNetAddress::optional(inDbLocation)),
inAccessRequest,
inAccessCred,
inOpenParameters));
secdebug("dbsession", "DbOpen returned handle %#lx", outDbHandle);
secdebug("dbsession", "********************");
}
CSSM_DB_HANDLE
DatabaseSession::insertDbContext(DbContext &inDbContext)
{
CSSM_DB_HANDLE aDbHandle;
try
{
aDbHandle = inDbContext.handle ();
StLock<Mutex> _(mDbContextMapLock);
mDbContextMap.insert(DbContextMap::value_type(aDbHandle, &inDbContext));
}
catch (...)
{
mDatabaseManager.dbClose(inDbContext);
throw;
}
return aDbHandle;
}
DbContext &
DatabaseSession::findDbContext(CSSM_DB_HANDLE inDbHandle)
{
StLock<Mutex> _(mDbContextMapLock);
DbContextMap::iterator it = mDbContextMap.find(inDbHandle);
if (it == mDbContextMap.end())
CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE);
return *it->second;
}
void
DatabaseSession::closeAll()
{
StLock<Mutex> _(mDbContextMapLock);
for (DbContextMap::iterator it = mDbContextMap.begin();
it != mDbContextMap.end();
it++)
{
DbContext *aDbContext = it->second;
try
{
mDatabaseManager.dbClose(*aDbContext);
}
catch (...)
{
}
}
mDbContextMap.clear();
secdebug("dbsession", "********************");
}
void
DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle)
{
StLock<Mutex> _(mDbContextMapLock);
DOCDebug("DatabaseSession::Close");
secdebug("dbsession", "DbClose of handle %ld", inDbHandle);
DbContextMap::iterator it = mDbContextMap.find(inDbHandle);
if (it == mDbContextMap.end())
CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE);
auto_ptr<DbContext> aDbContext(it->second);
mDbContextMap.erase(it);
mDatabaseManager.dbClose(*aDbContext);
secdebug("dbsession", "********************");
}
void
DatabaseSession::CreateRelation(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_RECORDTYPE inRelationID,
const char *inRelationName,
uint32 inNumberOfAttributes,
const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo,
uint32 inNumberOfIndexes,
const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo)
{
secdebug("dbsession", "CreateRelation from handle %ld of record type %X with relation name %s", inDbHandle, inRelationID, inRelationName);
secdebug("dbsession", "number of attributes = %d", inNumberOfAttributes);
#ifndef NDEBUG
unsigned n;
for (n = 0; n < inNumberOfAttributes; ++n)
{
secdebug("dbsession", "%d: id %d name %s, data type %d", n, inAttributeInfo[n].AttributeId,
inAttributeInfo[n].AttributeName,
inAttributeInfo[n].DataType);
}
#endif
secdebug("dbsession", "number of indexes: %d", inNumberOfIndexes);
#ifndef NDEBUG
for (n = 0; n < inNumberOfIndexes; ++n)
{
secdebug("dbsession", "%d: id %d indexid %d indextype %d location %d", n, inIndexInfo.AttributeId,
inIndexInfo.IndexedDataLocation,
inIndexInfo.IndexId,
inIndexInfo.IndexType);
}
#endif
DbContext &aDbContext = findDbContext(inDbHandle);
return aDbContext.mDatabase.createRelation(aDbContext, inRelationID, inRelationName,
inNumberOfAttributes, inAttributeInfo,
inNumberOfIndexes, inIndexInfo);
secdebug("dbsession", "********************");
}
void
DatabaseSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_RECORDTYPE inRelationID)
{
secdebug("dbsession", "DestroyRelation (handle %ld) %d", inDbHandle, inRelationID);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.destroyRelation(aDbContext, inRelationID);
secdebug("dbsession", "********************");
}
void
DatabaseSession::Authenticate(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_ACCESS_TYPE inAccessRequest,
const AccessCredentials &inAccessCred)
{
secdebug("dbsession", "Authenticate (handle %ld) inAccessRequest %d", inDbHandle, inAccessRequest);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.authenticate(aDbContext, inAccessRequest, inAccessCred);
secdebug("dbsession", "********************");
}
void
DatabaseSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle,
const CSSM_STRING *inSelectionTag,
uint32 &outNumberOfAclInfos,
CSSM_ACL_ENTRY_INFO_PTR &outAclInfos)
{
secdebug("dbsession", "GetDbAcl (handle %ld)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.getDbAcl(aDbContext, inSelectionTag, outNumberOfAclInfos, outAclInfos);
secdebug("dbsession", "********************");
}
void
DatabaseSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle,
const AccessCredentials &inAccessCred,
const CSSM_ACL_EDIT &inAclEdit)
{
secdebug("dbsession", "ChangeDbAcl (handle %ld)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.changeDbAcl(aDbContext, inAccessCred, inAclEdit);
secdebug("dbsession", "********************");
}
void
DatabaseSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle,
CSSM_ACL_OWNER_PROTOTYPE &outOwner)
{
secdebug("dbsession", "GetDbOwner (handle %ld)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.getDbOwner(aDbContext, outOwner);
secdebug("dbsession", "********************");
}
void
DatabaseSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle,
const AccessCredentials &inAccessCred,
const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner)
{
secdebug("dbsession", "ChangeDbOwner (handle %ld)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.changeDbOwner(aDbContext, inAccessCred, inNewOwner);
secdebug("dbsession", "********************");
}
void
DatabaseSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle,
char **outDbName)
{
secdebug("dbsession", "GetDbNameFromHandle (handle %ld)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
Required(outDbName) = aDbContext.mDatabase.getDbNameFromHandle(aDbContext);
secdebug("dbsession", "name: %s", *outDbName);
secdebug("dbsession", "********************");
}
#ifndef NDEBUG
#if 0
static
void DumpAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &info)
{
const char* attrNameType;
switch (info.AttributeFormat)
{
case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_STRING";
break;
case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_OID";
break;
case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
attrNameType = "CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER";
break;
}
secdebug("dbsession", " Attribute name type: %s", attrNameType);
switch (info.AttributeFormat)
{
case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
secdebug("dbsession", " name: %s", info.Label.AttributeName);
break;
case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER:
secdebug("dbsession", " name: %d", info.Label.AttributeID);
break;
case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
secdebug("dbsession", " name is oid");
break;
}
const char* s;
switch (info.AttributeFormat)
{
case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
s = "CSSM_DB_ATTRIBUTE_FORMAT_STRING";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
s = "CSSM_DB_ATTRIBUTE_FORMAT_SINT32";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
s = "CSSM_DB_ATTRIBUTE_FORMAT_UINT32";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
s = "CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_REAL:
s = "CSSM_DB_ATTRIBUTE_FORMAT_REAL";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
s = "CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
s = "CSSM_DB_ATTRIBUTE_FORMAT_BLOB";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
s = "CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32";
break;
case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX:
s = "CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX";
break;
}
secdebug("dbsession", " attribute format: %s", s);
}
static
void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes)
{
if (!inAttributes)
{
secdebug("dbsession", "No attributes defined.");
return;
}
secdebug("dbsession", "insert into %d", inAttributes->DataRecordType);
secdebug("dbsession", "Semantic information %d", inAttributes->SemanticInformation);
secdebug("dbsession", "Number of attributes: %d", inAttributes->NumberOfAttributes);
unsigned n;
for (n = 0; n < inAttributes->NumberOfAttributes; ++n)
{
DumpAttributeInfo(inAttributes->AttributeData[n].Info);
secdebug("dbsession", "Attribute %d\n", n);
secdebug("dbsession", " number of values: %d", inAttributes->AttributeData[n].NumberOfValues);
unsigned i;
for (i = 0; i < inAttributes->AttributeData[n].NumberOfValues; ++i)
{
switch (inAttributes->AttributeData[n].Info.AttributeFormat)
{
case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
{
std::string ss((char*) inAttributes->AttributeData[n].Value[i].Data, inAttributes->AttributeData[n].Value[i].Length);
secdebug("dbsession", " Value %d: %s", i, ss.c_str());
break;
}
case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
secdebug("dbsession", " Value %d: %d", i, *(sint32*)inAttributes->AttributeData[n].Value[i].Data);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
secdebug("dbsession", " Value %d: %u", i, *(uint32*)inAttributes->AttributeData[n].Value[i].Data);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
secdebug("dbsession", " Value %d: (bignum)", i);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_REAL:
secdebug("dbsession", " Value %d: %f", i, *(double*)inAttributes->AttributeData[n].Value[i].Data);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE:
secdebug("dbsession", " Value %d: %s", i, (char*)inAttributes->AttributeData[n].Value[i].Data);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
secdebug("dbsession", " Value %d: (blob)", i);
break;
case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
{
unsigned long j;
unsigned long numInts = inAttributes->AttributeData[n].Value[i].Length / sizeof(UInt32);
for (j = 0; j < numInts; ++j)
{
uint32* nums = (uint32*) inAttributes->AttributeData[n].Value[i].Data;
secdebug("dbsession", " %d", nums[j]);
}
break;
}
case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX:
secdebug("dbsession", " Value %d: (complex)", i);
break;
}
}
}
}
#endif
static void
DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record)
{
std::string output;
char hexBuffer[4];
unsigned i;
for (i = 0; i < record.RecordIdentifier.Length; ++i)
{
sprintf(hexBuffer, "%02X", record.RecordIdentifier.Data[i]);
output += hexBuffer;
}
secdebug("dbsession", " RecordIdentifier.Data: %s", output.c_str());
}
#endif
void
DatabaseSession::DataInsert(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_RECORDTYPE inRecordType,
const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
const CssmData *inData,
CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId)
{
secdebug("dbsession", "%p DataInsert(%lx,%x)", this, inDbHandle, inRecordType);
DbContext &aDbContext = findDbContext(inDbHandle);
outUniqueId = aDbContext.mDatabase.dataInsert(aDbContext, inRecordType, inAttributes, inData);
#ifndef NDEBUG
secdebug("dbsession", "Returned unique id:");
DumpUniqueRecord(*outUniqueId);
#endif
secdebug("dbsession", "********************");
}
void
DatabaseSession::DataDelete(CSSM_DB_HANDLE inDbHandle,
const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
{
secdebug("dbsession", "%p DataDelete(%lx)", this, inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.dataDelete(aDbContext, inUniqueRecordIdentifier);
#ifndef NDEBUG
secdebug("dbsession", "Record identifier:");
DumpUniqueRecord(inUniqueRecordIdentifier);
#endif
secdebug("dbsession", "********************");
}
void
DatabaseSession::DataModify(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_RECORDTYPE inRecordType,
CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier,
const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified,
const CssmData *inDataToBeModified,
CSSM_DB_MODIFY_MODE inModifyMode)
{
secdebug("dbsession", "%p DataModify(%lx,%x)", this, inDbHandle, inRecordType);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.dataModify(aDbContext, inRecordType, inoutUniqueRecordIdentifier,
inAttributesToBeModified, inDataToBeModified, inModifyMode);
#ifndef NDEBUG
secdebug("dbsession", "Out record identifier:");
DumpUniqueRecord(inoutUniqueRecordIdentifier);
#endif
secdebug("dbsession", "********************");
}
CSSM_HANDLE
DatabaseSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle,
const CssmQuery *inQuery,
CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
CssmData *inoutData,
CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId)
{
secdebug("dbsession", "%p DataGetFirst(%lx)", this, inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
CSSM_HANDLE result = aDbContext.mDatabase.dataGetFirst(aDbContext, inQuery,
inoutAttributes, inoutData, outUniqueId);
#ifndef NDEBUG
secdebug("dbsession", "result handle: %lx", result);
if (result != 0)
{
secdebug("dbsession", "Returned ID:");
DumpUniqueRecord(*outUniqueId);
}
#endif
secdebug("dbsession", "********************");
return result;
}
bool
DatabaseSession::DataGetNext(CSSM_DB_HANDLE inDbHandle,
CSSM_HANDLE inResultsHandle,
CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
CssmData *inoutData,
CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord)
{
secdebug("dbsession", "DataGetNext(%lx)", inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
bool result = aDbContext.mDatabase.dataGetNext(aDbContext, inResultsHandle, inoutAttributes,
inoutData, outUniqueRecord);
#ifndef NDEBUG
if (result)
{
secdebug("dbsession", "Returned ID:");
DumpUniqueRecord(*outUniqueRecord);
}
#endif
secdebug("dbsession", "********************");
return result;
}
void
DatabaseSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle,
CSSM_HANDLE inResultsHandle)
{
secdebug("dbsession", "%p DataAbortQuery(%lx)", this, inDbHandle);
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.dataAbortQuery(aDbContext, inResultsHandle);
secdebug("dbsession", "********************");
}
void
DatabaseSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle,
const CSSM_DB_UNIQUE_RECORD &inUniqueRecord,
CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
CssmData *inoutData)
{
secdebug("dbsession", "%p DataGetFromUniqueId(%lx)", this, inDbHandle);
#ifndef NDEBUG
secdebug("dbsession", "inUniqueRecord:");
DumpUniqueRecord(inUniqueRecord);
#endif
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.dataGetFromUniqueRecordId(aDbContext, inUniqueRecord,
inoutAttributes, inoutData);
secdebug("dbsession", "********************");
}
void
DatabaseSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle,
CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier)
{
secdebug("dbsession", "FreeUniqueRecord: %lx", inDbHandle);
#ifndef NDEBUG
secdebug("dbsession", "inUniqueRecordIdentifier follows:");
DumpUniqueRecord(inUniqueRecordIdentifier);
#endif
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.freeUniqueRecord(aDbContext, inUniqueRecordIdentifier);
secdebug("dbsession", "********************");
}
void
DatabaseSession::PassThrough(CSSM_DB_HANDLE inDbHandle,
uint32 passThroughId,
const void *inputParams,
void **outputParams)
{
DbContext &aDbContext = findDbContext(inDbHandle);
aDbContext.mDatabase.passThrough(aDbContext, passThroughId, inputParams, outputParams);
}