2 * Copyright (c) 2000-2001,2011-2014 Apple 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>
33 #include <utilities/debugging.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()
83 secerror("Object %p still has %d children at delete.\n", this, i
);
86 // release parent from her obligations (if we still have one)
88 mParent
->removeChild();
92 return; // Prevent re-throw of exception [function-try-block]
96 ObjectImpl::addChild()
98 mChildCount
++; // atomic
102 ObjectImpl::removeChild()
104 mChildCount
--; // atomic
109 // Manage allocators in the Object tree
112 ObjectImpl::allocator() const
114 StLock
<Mutex
> _(mAllocatorMutex
);
115 if (mAllocator
== NULL
)
119 mAllocator
= &mParent
->allocator();
121 mAllocator
= &Allocator::standard();
128 ObjectImpl::allocator(Allocator
&alloc
)
130 StLock
<Mutex
> _(mAllocatorMutex
);
131 assert(mAllocator
== NULL
); // cannot redefine allocator once set
135 // Comparison operators use pointer comparison by default. Subclasses may override.
137 ObjectImpl::operator <(const ObjectImpl
&other
) const
139 return this < &other
;
143 ObjectImpl::operator ==(const ObjectImpl
&other
) const
145 return this == &other
;
150 // CSSMSession objects.
151 // parent ::= NULL (none)
152 // active ::= CSSM initialized
154 ModuleNexus
<CssmImpl::StandardCssm
> CssmImpl::mStandard
;
156 CssmImpl::CssmImpl() : ObjectImpl()
159 mStandard().setCssm(this);
162 CssmImpl::CssmImpl(bool) : ObjectImpl()
165 // implicitly constructed - caller responsible for standard session management
168 CssmImpl::~CssmImpl()
176 // this may be the standard session...
177 mStandard().unsetCssm(this);
184 // set default configuration
187 mScope
= CSSM_PRIVILEGE_SCOPE_PROCESS
;
194 return Cssm(mStandard().get());
201 StLock
<Mutex
> _(mActivateMutex
);
204 // currently, no choices on PVC mode and key hierarchy
205 CSSM_PVC_MODE pvc
= CSSM_PVC_NONE
;
206 switch (CSSM_RETURN rc
= CSSM_Init(&mVersion
,
207 mScope
, &mCallerGuid
,
208 CSSM_KEY_HIERARCHY_NONE
, &pvc
, NULL
)) {
209 case CSSMERR_CSSM_PVC_ALREADY_CONFIGURED
:
220 CssmImpl::deactivate()
222 StLock
<Mutex
> _(mActivateMutex
);
227 // clear module map (all gone now)
228 moduleMap
.erase(moduleMap
.begin(), moduleMap
.end());
230 // now terminate CSSM
231 check(CSSM_Terminate());
236 CssmImpl::atExitHandler()
245 CssmImpl::catchExit()
247 // @@@ Even though this is the "right thing" to do. This only causes
248 // exceptions during exit and doesn't really help cleanup correctly.
250 if (::atexit(atExitHandler
))
251 UnixError::throwMe();
257 // Manage the automatic Cssm object.
258 // This is a program global.
260 void CssmImpl::StandardCssm::setCssm(CssmImpl
*cssm
)
262 StLock
<Mutex
> _(*this);
267 void CssmImpl::StandardCssm::unsetCssm(CssmImpl
*cssm
)
269 StLock
<Mutex
> _(*this);
274 Cssm
CssmImpl::StandardCssm::get()
276 StLock
<Mutex
> _(*this);
277 if (mCssm
== NULL
) { // make the default instance
278 mCssm
= new CssmImpl(true);
283 CssmImpl::StandardCssm::~StandardCssm()
293 // Auto-module management
296 CssmImpl::autoModule(const Guid
&guid
)
298 StLock
<Mutex
> _(mapLock
);
299 ModuleMap::iterator it
= moduleMap
.find(guid
);
300 if (it
== moduleMap
.end())
302 // no automodule for this guid yet, create one
303 Module
module(guid
, Cssm(this));
304 moduleMap
.insert(ModuleMap::value_type(guid
, module));
309 // existing automodule - use it
317 // parent ::= the session object (usually Cssm::standard)
318 // active ::= module is loaded.
320 ModuleImpl::ModuleImpl(const Guid
&guid
) : ObjectImpl(Cssm::standard()),
321 mAppNotifyCallback(NULL
),
322 mAppNotifyCallbackCtx(NULL
)
327 ModuleImpl::ModuleImpl(const Guid
&guid
, const Cssm
&session
) : ObjectImpl(session
),
328 mAppNotifyCallback(NULL
),
329 mAppNotifyCallbackCtx(NULL
)
334 ModuleImpl::~ModuleImpl()
341 // RawModuleEvent objects encapsulate CSSM module callbacks
343 RawModuleEvents::~RawModuleEvents()
346 CSSM_RETURN
RawModuleEvents::sendNotify(const CSSM_GUID
*, void *context
,
347 uint32 subService
, CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
)
350 reinterpret_cast<RawModuleEvents
*>(context
)->notify(subService
, type
, event
);
352 } catch (const CommonError
&error
) {
353 return CssmError::cssmError(error
, CSSM_CSSM_BASE_ERROR
);
355 return CSSMERR_CSSM_INTERNAL_ERROR
; // whatever...
361 // ModuleEvents enhance RawModuleEvents by splitting the callback up by type
363 void ModuleEvents::notify(uint32 subService
,
364 CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
)
367 case CSSM_NOTIFY_INSERT
:
368 insertion(subService
, type
);
370 case CSSM_NOTIFY_REMOVE
:
371 removal(subService
, type
);
373 case CSSM_NOTIFY_FAULT
:
374 fault(subService
, type
);
379 // default callbacks do nothing
380 void ModuleEvents::insertion(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
381 void ModuleEvents::removal(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
382 void ModuleEvents::fault(uint32 subService
, CSSM_SERVICE_TYPE type
) { }
386 ModuleImpl::appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback
, void *appNotifyCallbackCtx
)
388 secinfo("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p",
389 appNotifyCallback
, appNotifyCallbackCtx
);
391 Error::throwMe(Error::objectBusy
);
393 mAppNotifyCallback
= appNotifyCallback
;
394 mAppNotifyCallbackCtx
= appNotifyCallbackCtx
;
398 ModuleImpl::appNotifyCallback(RawModuleEvents
*handler
)
400 appNotifyCallback(RawModuleEvents::sendNotify
, handler
);
404 ModuleImpl::activate()
407 StLock
<Mutex
> _(mActivateMutex
);
411 // @@@ install handler here (use central dispatch with override)
412 secinfo("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p",
413 mAppNotifyCallback
, mAppNotifyCallbackCtx
);
414 check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE
, mAppNotifyCallback
, mAppNotifyCallbackCtx
));
419 session()->catchExit();
423 ModuleImpl::deactivate()
426 Error::throwMe(Error::objectBusy
);
428 StLock
<Mutex
> _(mActivateMutex
);
432 check(CSSM_ModuleUnload(&guid(), mAppNotifyCallback
, mAppNotifyCallbackCtx
));
437 ModuleImpl::session() const
439 return parent
<Cssm
>();
444 // CssmAttachment objects.
445 // parent ::= the loaded module object.
446 // active ::= attached.
448 AttachmentImpl::AttachmentImpl(const Guid
&guid
, CSSM_SERVICE_TYPE subserviceType
)
449 : ObjectImpl(CssmImpl::standard()->autoModule(guid
))
451 make(subserviceType
);
454 AttachmentImpl::AttachmentImpl(const Module
&module, CSSM_SERVICE_TYPE subserviceType
)
457 make(subserviceType
);
460 AttachmentImpl::~AttachmentImpl()
470 AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType
)
472 // default configuration
475 mSubserviceType
= subserviceType
;
481 AttachmentImpl::activate()
483 StLock
<Mutex
> _(mActivateMutex
);
487 mMemoryFunctions
= CssmAllocatorMemoryFunctions(allocator());
488 check(CSSM_ModuleAttach(&guid(), &mVersion
,
493 CSSM_KEY_HIERARCHY_NONE
,
494 NULL
, 0, // no function pointer table return
502 AttachmentImpl::deactivate()
504 StLock
<Mutex
> _(mActivateMutex
);
508 check(CSSM_ModuleDetach(mHandle
));
513 AttachmentImpl::subserviceMask() const
515 return mSubserviceType
;
519 AttachmentImpl::subserviceId(uint32 id
)
525 AttachmentImpl::subserviceUid() const
527 return CssmSubserviceUid(guid(), &mVersion
, mSubserviceId
, subserviceMask());
531 AttachmentImpl::module() const
533 return parent
<Module
>();