DynamicDLDBList.cpp [plain text]
#include "DynamicDLDBList.h"
#include "Globals.h"
#include <security_utilities/debugging.h>
#include <security_cdsa_utilities/cssmbridge.h> // For Required()
#include <security_cdsa_client/mdsclient.h>
#include <security_cdsa_client/mds_standard.h>
#include "KCEventNotifier.h"
using namespace KeychainCore;
DynamicDLDBList::DynamicDLDBList()
: mMutex(Mutex::recursive), mSearchListSet(false)
{
}
DynamicDLDBList::~DynamicDLDBList()
{
}
CSSM_RETURN
DynamicDLDBList::appNotifyCallback(const CSSM_GUID *guid, void *context,
uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType)
{
CSSM_RETURN status = 0;
try
{
reinterpret_cast<DynamicDLDBList *>(context)->callback(Guid::required(guid),
subserviceId, subserviceType, eventType);
}
catch (const CommonError &error)
{
status = error.osStatus();
}
catch (...)
{
}
return status;
}
bool
DynamicDLDBList::_add(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType)
{
return _add(dlDbIdentifier(guid, subserviceID, subserviceType));
}
bool
DynamicDLDBList::_add(const DLDbIdentifier &dlDbIdentifier)
{
StLock<Mutex>_(mMutex);
if (find(mSearchList.begin(), mSearchList.end(), dlDbIdentifier) == mSearchList.end())
{
mSearchList.push_back(dlDbIdentifier);
return true;
}
return false;
}
bool
DynamicDLDBList::_remove(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType)
{
return _remove(dlDbIdentifier(guid, subserviceID, subserviceType));
}
bool
DynamicDLDBList::_remove(const DLDbIdentifier &dlDbIdentifier)
{
StLock<Mutex>_(mMutex);
for (SearchList::iterator it = mSearchList.begin(); it != mSearchList.end(); it++)
if (it->ssuid() == dlDbIdentifier.ssuid())
{
mSearchList.erase(it);
globals().storageManager.didRemoveKeychain(dlDbIdentifier);
return true;
}
return false;
}
bool
DynamicDLDBList::_load()
{
StLock<Mutex>_(mMutex);
bool list_changed = false;
MDSClient::Directory &mds = MDSClient::mds();
MDSClient::Table<MDSClient::Common> common(mds);
MDSClient::Table<MDSClient::DL> dl(mds);
MDSClient::Table<MDSClient::CSP> csp(mds);
for (MDSClient::Table<MDSClient::Common>::iterator commonIt =
common.find(MDSClient::Attribute("DynamicFlag") != false);
commonIt != common.end(); ++commonIt)
{
CSSM_SERVICE_MASK serviceMask = (*commonIt)->serviceMask();
if (serviceMask & CSSM_SERVICE_DL)
{
string moduleID = (*commonIt)->moduleID();
secinfo("dynamic", "Loading dynamic %sDL module: %s",
(serviceMask & CSSM_SERVICE_CSP) ? "CSP/" : "", moduleID.c_str());
Guid moduleGuid(moduleID);
CssmClient::Module module(moduleGuid);
module->appNotifyCallback(appNotifyCallback, this);
module->load();
mModules.push_back(module);
for (MDSClient::Table<MDSClient::DL>::iterator dlIt =
dl.find(MDSClient::Attribute("ModuleID") == moduleID);
dlIt!= dl.end(); ++dlIt)
{
uint32 subserviceID = (*dlIt)->subserviceID();
bool hasCSP = csp.find(MDSClient::Attribute("ModuleID") == moduleID
&& MDSClient::Attribute("SSID") == subserviceID) != csp.end();
secinfo("dynamic", "Adding databases from %sDL SSID %lu module: %s",
hasCSP ? "CSP/" : "", (unsigned long)subserviceID, moduleID.c_str());
list_changed |= _add(moduleGuid, subserviceID,
hasCSP ? CSSM_SERVICE_CSP | CSSM_SERVICE_DL : CSSM_SERVICE_DL);
}
}
}
return list_changed;
}
const vector<DLDbIdentifier> &
DynamicDLDBList::searchList()
{
StLock<Mutex>_(mMutex);
if (!mSearchListSet)
{
_load();
mSearchListSet = true;
}
return mSearchList;
}
void
DynamicDLDBList::callback(const Guid &guid, uint32 subserviceID,
CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType)
{
secinfo("event", "Received callback from guid: %s ssid: %lu type: %lu event: %lu",
guid.toString().c_str(), (unsigned long)subserviceID, (unsigned long)subserviceType, (unsigned long)eventType);
StLock<Mutex>_(mMutex);
bool list_changed = false;
if (subserviceType & CSSM_SERVICE_DL)
{
if (eventType == CSSM_NOTIFY_INSERT)
{
secinfo("dynamic", "%sDL module: %s SSID: %lu inserted",
(subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID);
list_changed = _add(guid, subserviceID, subserviceType);
}
else if (eventType == CSSM_NOTIFY_REMOVE)
{
secinfo("dynamic", "%sDL module: %s SSID: %lu removed",
(subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID);
list_changed = _remove(guid, subserviceID, subserviceType);
}
}
if (list_changed)
{
KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent);
}
}
DLDbIdentifier DynamicDLDBList::dlDbIdentifier(const Guid &guid,
uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType)
{
CSSM_VERSION theVersion={};
CssmSubserviceUid ssuid(guid, &theVersion, subserviceID, subserviceType);
CssmNetAddress *dbLocation=NULL;
return DLDbIdentifier(ssuid, NULL, dbLocation);
}