#include <security_cdsa_client/cssmclient.h>
#include <utilities/debugging.h>
using namespace CssmClient;
const char *
Error::what () const throw()
{
return "CSSM client library error";
}
void
ObjectImpl::check(CSSM_RETURN status)
{
if (status != CSSM_OK)
{
CssmError::throwMe(status);
}
}
ObjectImpl::ObjectImpl() : mParent(), mChildCount(0)
{
mActive = false; mAllocator = NULL; }
ObjectImpl::ObjectImpl(const Object &mommy) : mParent(mommy.mImpl), mChildCount(0)
{
mActive = false; mAllocator = NULL; if (mParent)
mParent->addChild();
}
ObjectImpl::~ObjectImpl()
try
{
if (!isIdle())
{
int i = mChildCount;
secerror("Object %p still has %d children at delete.\n", this, i);
}
if (mParent)
mParent->removeChild();
}
catch(...)
{
return;
}
void
ObjectImpl::addChild()
{
mChildCount++; }
void
ObjectImpl::removeChild()
{
mChildCount--; }
Allocator &
ObjectImpl::allocator() const
{
if (mAllocator == NULL)
{
if (mParent)
mAllocator = &mParent->allocator();
else
mAllocator = &Allocator::standard();
}
return *mAllocator;
}
void
ObjectImpl::allocator(Allocator &alloc)
{
assert(mAllocator == NULL); mAllocator = &alloc;
}
bool
ObjectImpl::operator <(const ObjectImpl &other) const
{
return this < &other;
}
bool
ObjectImpl::operator ==(const ObjectImpl &other) const
{
return this == &other;
}
ModuleNexus<CssmImpl::StandardCssm> CssmImpl::mStandard;
CssmImpl::CssmImpl() : ObjectImpl()
{
setup();
mStandard().setCssm(this);
}
CssmImpl::CssmImpl(bool) : ObjectImpl()
{
setup();
}
CssmImpl::~CssmImpl()
{
try
{
deactivate();
}
catch(...) {}
mStandard().unsetCssm(this);
}
void
CssmImpl::setup()
{
mVersion.Major = 2;
mVersion.Minor = 0;
mScope = CSSM_PRIVILEGE_SCOPE_PROCESS;
}
Cssm
CssmImpl::standard()
{
return Cssm(mStandard().get());
}
void
CssmImpl::activate()
{
StLock<Mutex> _(mActivateMutex);
if (!mActive)
{
CSSM_PVC_MODE pvc = CSSM_PVC_NONE;
switch (CSSM_RETURN rc = CSSM_Init(&mVersion,
mScope, &mCallerGuid,
CSSM_KEY_HIERARCHY_NONE, &pvc, NULL)) {
case CSSMERR_CSSM_PVC_ALREADY_CONFIGURED:
case CSSM_OK:
break;
default:
check(rc);
}
mActive = true;
}
}
void
CssmImpl::deactivate()
{
StLock<Mutex> _(mActivateMutex);
if (mActive)
{
mActive = false;
moduleMap.erase(moduleMap.begin(), moduleMap.end());
check(CSSM_Terminate());
}
}
void
CssmImpl::atExitHandler()
{
try {
mStandard.reset();
} catch (...) {
}
}
void
CssmImpl::catchExit()
{
#if 0
if (::atexit(atExitHandler))
UnixError::throwMe();
#endif
}
void CssmImpl::StandardCssm::setCssm(CssmImpl *cssm)
{
StLock<Mutex> _(*this);
if (mCssm == NULL)
mCssm = cssm;
}
void CssmImpl::StandardCssm::unsetCssm(CssmImpl *cssm)
{
StLock<Mutex> _(*this);
if (mCssm == cssm)
mCssm = NULL;
}
Cssm CssmImpl::StandardCssm::get()
{
StLock<Mutex> _(*this);
if (mCssm == NULL) { mCssm = new CssmImpl(true);
}
return Cssm(mCssm);
}
CssmImpl::StandardCssm::~StandardCssm()
{
if (mCssm) {
mCssm->deactivate();
delete mCssm;
}
}
Module
CssmImpl::autoModule(const Guid &guid)
{
StLock<Mutex> _(mapLock);
ModuleMap::iterator it = moduleMap.find(guid);
if (it == moduleMap.end())
{
Module module(guid, Cssm(this));
moduleMap.insert(ModuleMap::value_type(guid, module));
return module;
}
else
{
return it->second;
}
}
ModuleImpl::ModuleImpl(const Guid &guid) : ObjectImpl(Cssm::standard()),
mAppNotifyCallback(NULL),
mAppNotifyCallbackCtx(NULL)
{
setGuid(guid);
}
ModuleImpl::ModuleImpl(const Guid &guid, const Cssm &session) : ObjectImpl(session),
mAppNotifyCallback(NULL),
mAppNotifyCallbackCtx(NULL)
{
setGuid(guid);
}
ModuleImpl::~ModuleImpl()
{
unload();
}
RawModuleEvents::~RawModuleEvents()
{ }
CSSM_RETURN RawModuleEvents::sendNotify(const CSSM_GUID *, void *context,
uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event)
{
try {
reinterpret_cast<RawModuleEvents *>(context)->notify(subService, type, event);
return CSSM_OK;
} catch (const CommonError &error) {
return CssmError::cssmError(error, CSSM_CSSM_BASE_ERROR);
} catch (...) {
return CSSMERR_CSSM_INTERNAL_ERROR; }
}
void ModuleEvents::notify(uint32 subService,
CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event)
{
switch (event) {
case CSSM_NOTIFY_INSERT:
insertion(subService, type);
break;
case CSSM_NOTIFY_REMOVE:
removal(subService, type);
break;
case CSSM_NOTIFY_FAULT:
fault(subService, type);
break;
}
}
void ModuleEvents::insertion(uint32 subService, CSSM_SERVICE_TYPE type) { }
void ModuleEvents::removal(uint32 subService, CSSM_SERVICE_TYPE type) { }
void ModuleEvents::fault(uint32 subService, CSSM_SERVICE_TYPE type) { }
void
ModuleImpl::appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx)
{
secinfo("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p",
appNotifyCallback, appNotifyCallbackCtx);
if (mActive)
Error::throwMe(Error::objectBusy);
mAppNotifyCallback = appNotifyCallback;
mAppNotifyCallbackCtx = appNotifyCallbackCtx;
}
void
ModuleImpl::appNotifyCallback(RawModuleEvents *handler)
{
appNotifyCallback(RawModuleEvents::sendNotify, handler);
}
void
ModuleImpl::activate()
{
{
StLock<Mutex> _(mActivateMutex);
if (!mActive)
{
session()->init();
secinfo("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p",
mAppNotifyCallback, mAppNotifyCallbackCtx);
check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE, mAppNotifyCallback, mAppNotifyCallbackCtx));
mActive = true;
}
}
session()->catchExit();
}
void
ModuleImpl::deactivate()
{
if (!isIdle())
Error::throwMe(Error::objectBusy);
StLock<Mutex> _(mActivateMutex);
if (mActive)
{
mActive = false;
check(CSSM_ModuleUnload(&guid(), mAppNotifyCallback, mAppNotifyCallbackCtx));
}
}
Cssm
ModuleImpl::session() const
{
return parent<Cssm>();
}
AttachmentImpl::AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType)
: ObjectImpl(CssmImpl::standard()->autoModule(guid))
{
make(subserviceType);
}
AttachmentImpl::AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType)
: ObjectImpl(module)
{
make(subserviceType);
}
AttachmentImpl::~AttachmentImpl()
{
detach();
}
void
AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType)
{
mVersion.Major = 2;
mVersion.Minor = 0;
mSubserviceType = subserviceType;
mSubserviceId = 0;
mAttachFlags = 0;
}
void
AttachmentImpl::activate()
{
StLock<Mutex> _(mActivateMutex);
if (!mActive)
{
module()->load();
mMemoryFunctions = CssmAllocatorMemoryFunctions(allocator());
check(CSSM_ModuleAttach(&guid(), &mVersion,
&mMemoryFunctions,
mSubserviceId,
mSubserviceType,
mAttachFlags,
CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &mHandle));
mActive = true;
}
}
void
AttachmentImpl::deactivate()
{
StLock<Mutex> _(mActivateMutex);
if (mActive)
{
mActive = false;
check(CSSM_ModuleDetach(mHandle));
}
}
CSSM_SERVICE_MASK
AttachmentImpl::subserviceMask() const
{
return mSubserviceType;
}
void
AttachmentImpl::subserviceId(uint32 id)
{
mSubserviceId = id;
}
CssmSubserviceUid
AttachmentImpl::subserviceUid() const
{
return CssmSubserviceUid(guid(), &mVersion, mSubserviceId, subserviceMask());
}
Module
AttachmentImpl::module() const
{
return parent<Module>();
}