2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // cssmclient - common client interface to CSSM and MDS.
22 // Locking Strategy (preliminary):
23 // XXX This is obsolete update this --mb
24 // A CssmObject is a CountingMutex. Its count represents the number of children that have registered
25 // themselves (using addChild/removeChild). The lock controls the internal management fields of the
26 // various subclasses to protect them against corruption. It does NOT control attribute and argument
27 // fields and operations, not does it control object-constant fields.
28 // This means that if you use an object from multiple threads, you (the caller) must lock the object
29 // during set/get calls of attributes. Note that the CSSM operations themselves are safely multithreaded
30 // and thus don't need to be interlocked explicitly.
32 #include <security_cdsa_client/cssmclient.h>
35 using namespace CssmClient
;
41 Error::what () const throw()
43 return "CSSM client library error";
51 ObjectImpl::check(CSSM_RETURN status
)
53 if (status
!= CSSM_OK
)
55 CssmError::throwMe(status
);
61 // Common features of Objects
63 ObjectImpl::ObjectImpl() : mParent(), mChildCount(0)
65 mActive
= false; // not activated
66 mAllocator
= NULL
; // allocator to be determined
69 ObjectImpl::ObjectImpl(const Object
&mommy
) : mParent(mommy
.mImpl
), mChildCount(0)
71 mActive
= false; // not activated
72 mAllocator
= NULL
; // allocator to be determined
77 ObjectImpl::~ObjectImpl()
80 assert(!mActive
); // subclass must have deactivated us
83 // release parent from her obligations (if we still have one)
85 mParent
->removeChild();
93 ObjectImpl::addChild()
95 mChildCount
++; // atomic
99 ObjectImpl::removeChild()
101 mChildCount
--; // atomic
106 // Manage allocators in the Object tree
109 ObjectImpl::allocator() const
111 if (mAllocator
== NULL
)
115 mAllocator
= &mParent
->allocator();
117 mAllocator
= &Allocator::standard();
124 ObjectImpl::allocator(Allocator
&alloc
)
126 assert(mAllocator
== NULL
); // cannot redefine allocator once set
130 // Comparison operators use pointer comparison by default. Subclasses may override.
132 ObjectImpl::operator <(const ObjectImpl
&other
) const
134 return this < &other
;
138 ObjectImpl::operator ==(const ObjectImpl
&other
) const
140 return this == &other
;
145 // CSSMSession objects.
146 // parent ::= NULL (none)
147 // active ::= CSSM initialized
149 ModuleNexus
<CssmImpl::StandardCssm
> CssmImpl::mStandard
;
151 CssmImpl::CssmImpl() : ObjectImpl()
154 mStandard().setCssm(this);
157 CssmImpl::CssmImpl(bool) : ObjectImpl()
160 // implicitly constructed - caller responsible for standard session management
163 CssmImpl::~CssmImpl()
171 // this may be the standard session...
172 mStandard().unsetCssm(this);
179 // set default configuration
182 mScope
= CSSM_PRIVILEGE_SCOPE_PROCESS
;
189 return Cssm(mStandard().get());
196 StLock
<Mutex
> _(mActivateMutex
);
199 // currently, no choices on PVC mode and key hierarchy
200 CSSM_PVC_MODE pvc
= CSSM_PVC_NONE
;
201 switch (CSSM_RETURN rc
= CSSM_Init(&mVersion
,
202 mScope
, &mCallerGuid
,
203 CSSM_KEY_HIERARCHY_NONE
, &pvc
, NULL
)) {
204 case CSSMERR_CSSM_PVC_ALREADY_CONFIGURED
:
215 CssmImpl::deactivate()
217 StLock
<Mutex
> _(mActivateMutex
);
222 // clear module map (all gone now)
223 moduleMap
.erase(moduleMap
.begin(), moduleMap
.end());
225 // now terminate CSSM
226 check(CSSM_Terminate());
231 CssmImpl::atExitHandler()
240 CssmImpl::catchExit()
242 // @@@ Even though this is the "right thing" to do. This only causes
243 // exceptions during exit and doesn't really help cleanup correctly.
245 if (::atexit(atExitHandler
))
246 UnixError::throwMe();
252 // Manage the automatic Cssm object.
253 // This is a program global.
255 void CssmImpl::StandardCssm::setCssm(CssmImpl
*cssm
)
257 StLock
<Mutex
> _(*this);
262 void CssmImpl::StandardCssm::unsetCssm(CssmImpl
*cssm
)
264 StLock
<Mutex
> _(*this);
269 CssmImpl
*CssmImpl::StandardCssm::get()
271 StLock
<Mutex
> _(*this);
272 if (mCssm
== NULL
) { // make the default instance
273 mCssm
= new CssmImpl(true);
278 CssmImpl::StandardCssm::~StandardCssm()
288 // Auto-module management
291 CssmImpl::autoModule(const Guid
&guid
)
293 StLock
<Mutex
> _(mapLock
);
294 ModuleMap::iterator it
= moduleMap
.find(guid
);
295 if (it
== moduleMap
.end())
297 // no automodule for this guid yet, create one
298 Module
module(guid
, Cssm(this));
299 moduleMap
.insert(ModuleMap::value_type(guid
, module));
304 // existing automodule - use it
312 // parent ::= the session object (usually Cssm::standard)
313 // active ::= module is loaded.
315 ModuleImpl::ModuleImpl(const Guid
&guid
) : ObjectImpl(Cssm::standard()),
316 mAppNotifyCallback(NULL
),
317 mAppNotifyCallbackCtx(NULL
)
322 ModuleImpl::ModuleImpl(const Guid
&guid
, const Cssm
&session
) : ObjectImpl(session
),
323 mAppNotifyCallback(NULL
),
324 mAppNotifyCallbackCtx(NULL
)
329 ModuleImpl::~ModuleImpl()
336 // RawModuleEvent objects encapsulate CSSM module callbacks
338 RawModuleEvents::~RawModuleEvents()
341 CSSM_RETURN
RawModuleEvents::sendNotify(const CSSM_GUID
*, void *context
,
342 uint32 subService
, CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
)
345 reinterpret_cast<RawModuleEvents
*>(context
)->notify(subService
, type
, event
);
347 } catch (const CommonError
&error
) {
348 return CssmError::cssmError(error
, CSSM_CSSM_BASE_ERROR
);
350 return CSSMERR_CSSM_INTERNAL_ERROR
; // whatever...
356 // ModuleEvents enhance RawModuleEvents by splitting the callback up by type
358 void ModuleEvents::notify(uint32 subService
,
359 CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
)
362 case CSSM_NOTIFY_INSERT
:
363 insertion(subService
, type
);
365 case CSSM_NOTIFY_REMOVE
:
366 removal(subService
, type
);
368 case CSSM_NOTIFY_FAULT
:
369 fault(subService
, type
);
374 // default callbacks do nothing
375 void ModuleEvents::insertion(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
376 void ModuleEvents::removal(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
377 void ModuleEvents::fault(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
381 ModuleImpl::appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback
, void *appNotifyCallbackCtx
)
383 secdebug("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p",
384 appNotifyCallback
, appNotifyCallbackCtx
);
386 Error::throwMe(Error::objectBusy
);
388 mAppNotifyCallback
= appNotifyCallback
;
389 mAppNotifyCallbackCtx
= appNotifyCallbackCtx
;
393 ModuleImpl::appNotifyCallback(RawModuleEvents
*handler
)
395 appNotifyCallback(RawModuleEvents::sendNotify
, handler
);
399 ModuleImpl::activate()
401 StLock
<Mutex
> _(mActivateMutex
);
405 // @@@ install handler here (use central dispatch with override)
406 secdebug("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p",
407 mAppNotifyCallback
, mAppNotifyCallbackCtx
);
408 check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE
, mAppNotifyCallback
, mAppNotifyCallbackCtx
));
410 session()->catchExit();
415 ModuleImpl::deactivate()
417 StLock
<Mutex
> _(mActivateMutex
);
419 Error::throwMe(Error::objectBusy
);
423 check(CSSM_ModuleUnload(&guid(), mAppNotifyCallback
, mAppNotifyCallbackCtx
));
428 ModuleImpl::session() const
430 return parent
<Cssm
>();
435 // CssmAttachment objects.
436 // parent ::= the loaded module object.
437 // active ::= attached.
439 AttachmentImpl::AttachmentImpl(const Guid
&guid
, CSSM_SERVICE_TYPE subserviceType
)
440 : ObjectImpl(CssmImpl::standard()->autoModule(guid
))
442 make(subserviceType
);
445 AttachmentImpl::AttachmentImpl(const Module
&module, CSSM_SERVICE_TYPE subserviceType
)
448 make(subserviceType
);
451 AttachmentImpl::~AttachmentImpl()
457 AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType
)
459 // default configuration
462 mSubserviceType
= subserviceType
;
468 AttachmentImpl::activate()
470 StLock
<Mutex
> _(mActivateMutex
);
474 mMemoryFunctions
= CssmAllocatorMemoryFunctions(allocator());
475 check(CSSM_ModuleAttach(&guid(), &mVersion
,
480 CSSM_KEY_HIERARCHY_NONE
,
481 NULL
, 0, // no function pointer table return
489 AttachmentImpl::deactivate()
491 StLock
<Mutex
> _(mActivateMutex
);
495 check(CSSM_ModuleDetach(mHandle
));
500 AttachmentImpl::subserviceMask() const
502 return mSubserviceType
;
506 AttachmentImpl::subserviceId(uint32 id
)
512 AttachmentImpl::subserviceUid() const
514 return CssmSubserviceUid(guid(), &mVersion
, mSubserviceId
, subserviceMask());
518 AttachmentImpl::module() const
520 return parent
<Module
>();