#include <Security/cssmclient.h>
#include <Security/cssmerrno.h>
using namespace CssmClient;
CSSM_RETURN
Error::cssmError() const
{
return CssmError::cssmError();
}
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()
{
assert(!mActive); if (!isIdle())
Error::throwMe(Error::objectBusy);
if (mParent)
mParent->removeChild();
}
void
ObjectImpl::addChild()
{
mChildCount++; }
void
ObjectImpl::removeChild()
{
mChildCount--; }
CssmAllocator &
ObjectImpl::allocator() const
{
if (mAllocator == NULL)
{
if (mParent)
mAllocator = &mParent->allocator();
else
mAllocator = &CssmAllocator::standard();
}
return *mAllocator;
}
void
ObjectImpl::allocator(CssmAllocator &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()
{
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()
{
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;
}
CssmImpl *CssmImpl::StandardCssm::get()
{
StLock<Mutex> _(*this);
if (mCssm == NULL) { mCssm = new CssmImpl(true);
}
return 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())
{
setGuid(guid);
}
ModuleImpl::ModuleImpl(const Guid &guid, const Cssm &session) : ObjectImpl(session)
{
setGuid(guid);
}
ModuleImpl::~ModuleImpl()
{
unload();
}
void
ModuleImpl::activate()
{
if (!mActive)
{
session()->init();
check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE, NULL, NULL));
mActive = true;
session()->catchExit();
}
}
void
ModuleImpl::deactivate()
{
if (!isIdle())
Error::throwMe(Error::objectBusy);
if (mActive)
{
mActive = false;
check(CSSM_ModuleUnload(&guid(), NULL, NULL));
}
}
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()
{
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()
{
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>();
}