#ifdef __MWERKS__
#define _CPP_MANAGER
#endif
#include "manager.h"
#include "module.h"
#include <Security/debugging.h>
CssmManager::CssmManager() : MdsComponent(gGuidCssm)
{
initCount = 0; }
CssmManager::~CssmManager()
{
if (initCount > 0)
debug("cssm", "CSSM forcibly shutting down");
}
void CssmManager::initialize (const CSSM_VERSION &version,
CSSM_PRIVILEGE_SCOPE scope,
const Guid &callerGuid,
CSSM_KEY_HIERARCHY keyHierarchy,
CSSM_PVC_MODE &pvcPolicy)
{
StLock<Mutex> _(mLock);
checkVersion(version);
if (initCount) {
if (pvcPolicy != mPvcPolicy) {
pvcPolicy = mPvcPolicy; CssmError::throwMe(CSSMERR_CSSM_PVC_ALREADY_CONFIGURED);
}
initCount++;
debug("cssm", "re-initializing CSSM (%d levels)", initCount);
return;
}
if (scope == CSSM_PRIVILEGE_SCOPE_THREAD)
CssmError::throwMe(CSSMERR_CSSM_SCOPE_NOT_SUPPORTED);
mPrivilegeScope = scope;
mKeyHierarchy = keyHierarchy;
mPvcPolicy = pvcPolicy;
mCallerGuid = callerGuid;
initCount = 1;
debug("cssm", "CSSM initialized");
}
bool CssmManager::terminate()
{
StLock<Mutex> _(mLock);
switch (initCount) {
case 0:
CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED);
case 1:
debug("cssm", "Terminating CSSM");
if (!moduleMap.empty())
CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); initCount = 0; return true;
default:
initCount--; debug("cssm", "CSSM nested termination (%d remaining)", initCount);
return false;
}
}
#if defined(RESTRICTED_CSP_LOADING)
static char *allowedCSPs[] = {
"/System/Library/Security/AppleCSP.bundle",
"/System/Library/Security/AppleCSPDL.bundle",
NULL
};
#endif
void CssmManager::loadModule(const Guid &guid,
CSSM_KEY_HIERARCHY,
const ModuleCallback &callback)
{
StLock<Mutex> _(mLock);
ModuleMap::iterator it = moduleMap.find(guid);
Module *module;
if (it == moduleMap.end()) {
MdsComponent info(guid);
#if defined(RESTRICTED_CSP_LOADING)
if (info.supportsService(CSSM_SERVICE_CSP)) {
string loadPath = info.path();
for (char **pp = allowedCSPs; *pp; pp++)
if (loadPath == *pp)
goto allowed;
CssmError::throwMe(CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED);
allowed: ;
}
#endif
module = new Module(this, info, loader(info.path()));
moduleMap[guid] = module;
} else {
module = it->second;
}
module->add(callback);
}
void CssmManager::unloadModule(const Guid &guid,
const ModuleCallback &callback)
{
StLock<Mutex> _(mLock);
Module *module = getModule(guid);
if (module->unload(callback)) {
moduleMap.erase(guid);
delete module;
}
}
void CssmManager::introduce(const Guid &,
CSSM_KEY_HIERARCHY)
{
StLock<Mutex> _(mLock);
CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
}
void CssmManager::unIntroduce(const Guid &)
{
StLock<Mutex> _(mLock);
CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
}
void CssmManager::checkVersion(const CSSM_VERSION &version)
{
if (version.Major != 2)
CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
if (version.Minor != 0)
CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
}
Module *CssmManager::getModule(const Guid &guid)
{
ModuleMap::iterator it = moduleMap.find(guid);
if (it == moduleMap.end())
CssmError::throwMe(CSSMERR_CSSM_MODULE_NOT_LOADED);
return it->second;
}