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() 
 466 AttachmentImpl::make(CSSM_SERVICE_TYPE subserviceType
) 
 468         // default configuration 
 471         mSubserviceType 
= subserviceType
; 
 477 AttachmentImpl::activate() 
 479     StLock
<Mutex
> _(mActivateMutex
); 
 483                 mMemoryFunctions 
= CssmAllocatorMemoryFunctions(allocator()); 
 484                 check(CSSM_ModuleAttach(&guid(), &mVersion
, 
 489                           CSSM_KEY_HIERARCHY_NONE
, 
 490                           NULL
, 0,      // no function pointer table return 
 498 AttachmentImpl::deactivate() 
 500     StLock
<Mutex
> _(mActivateMutex
); 
 504                 check(CSSM_ModuleDetach(mHandle
)); 
 509 AttachmentImpl::subserviceMask() const 
 511         return mSubserviceType
; 
 515 AttachmentImpl::subserviceId(uint32 id
) 
 521 AttachmentImpl::subserviceUid() const 
 523         return CssmSubserviceUid(guid(), &mVersion
, mSubserviceId
, subserviceMask()); 
 527 AttachmentImpl::module() const 
 529         return parent
<Module
>();