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 #ifndef _H_CDSA_CLIENT_CSSMCLIENT 
  23 #define _H_CDSA_CLIENT_CSSMCLIENT  1 
  25 #include <security_utilities/threading.h> 
  26 #include <security_utilities/globalizer.h> 
  27 #include <security_utilities/refcount.h> 
  28 #include <security_cdsa_utilities/cssmalloc.h> 
  29 #include <security_cdsa_utilities/cssmpods.h> 
  33 namespace CssmClient 
{ 
  37 // Forward declarations 
  45 // An mixin for objects that have (store) GUIDs. 
  46 // The GUID value is meant to be set-once constant, and can be lock-handled accordingly. 
  50         HasGuid(const Guid 
&guid
) { mGuid 
= guid
; } 
  53         const Guid 
&guid() const { return mGuid
; } 
  56         void setGuid(const Guid 
&guid
) { mGuid 
= guid
; } 
  64 // Exceptions are based on the CssmError utility class. We add our own class of client-side exceptions. 
  66 class Error 
: public CssmError 
{ 
  68         Error(CSSM_RETURN err
) : CssmError(err
) { } 
  69         virtual const char *what () const throw(); 
  78 // The CssmObject abstract class models features common to different Cssm objects. 
  79 // It handles a tree hierarchy of objects (parent/children) safely. 
  83 class ObjectImpl 
: virtual public RefCount
 
  86         explicit ObjectImpl(); // Constructor for Impl objects without a parent. 
  87         explicit ObjectImpl(const Object 
&parent
); 
  88         virtual ~ObjectImpl(); 
  90         bool isActive() const { return mActive
; } 
  92         virtual Allocator 
&allocator() const; 
  93         virtual void allocator(Allocator 
&alloc
); 
  95         // Pointer comparison by default.  Subclasses may override. 
  96         virtual bool operator <(const ObjectImpl 
&other
) const; 
  97         virtual bool operator ==(const ObjectImpl 
&other
) const; 
  99         static void check(CSSM_RETURN status
); 
 100         bool isIdle() const { return mChildCount 
== 0; } 
 103         bool mActive
;                                   // loaded, attached, etc. 
 104     RecursiveMutex mActivateMutex
; 
 105         mutable Allocator 
*mAllocator
; // allocator hierarchy (NULL => TBD) 
 106     mutable RecursiveMutex mAllocatorMutex
; // protects allocator creation 
 108         template <class Obj
> Obj 
parent() const 
 109         { assert(mParent
); return Obj(static_cast<typename 
Obj::Impl 
*>(&(*mParent
))); } 
 114         // {de,}activate() assume you have locked *this 
 115         virtual void activate() = 0; 
 116         virtual void deactivate() = 0; 
 119         RefPointer
<ObjectImpl
> mParent
;         // parent object 
 120         AtomicCounter
<uint32
> mChildCount
; 
 126         friend class ObjectImpl
; 
 128         typedef ObjectImpl Impl
; 
 129         explicit Object(Impl 
*impl
) : mImpl(impl
) {} 
 132         // @@@ CSPDL subclass breaks if the is a static_cast 
 133         template <class _Impl
> _Impl 
&impl() const 
 134         { return dynamic_cast<_Impl 
&>(*mImpl
); } 
 137         Impl 
*operator ->() const { return &(*mImpl
); } 
 138         Impl 
&operator *() const { return *mImpl
; } 
 140         // @@@ Why is this needed.  DbCursor which inheirits from Object wants to call this. 
 141         template <class _Impl
> _Impl 
&checkedImpl() const 
 142         { return dynamic_cast<_Impl 
&>(*mImpl
); } 
 144         bool operator !() const { return !mImpl
; } 
 145         operator bool() const { return mImpl
; } 
 147     bool isActive() const                               { return mImpl 
&& mImpl
->isActive(); } 
 148     Allocator 
&allocator() const        { return mImpl
->allocator(); } 
 149         void release()                                          { mImpl 
= NULL
; } 
 151         bool operator <(const Object 
&other
) const 
 152         { return mImpl 
&& other
.mImpl 
? *mImpl 
< *other
.mImpl 
: mImpl 
< other
.mImpl
; } 
 153         bool operator ==(const Object 
&other
) const 
 154         { return mImpl 
&& other
.mImpl 
? *mImpl 
== *other
.mImpl 
: mImpl 
== other
.mImpl
; } 
 156     Impl
* get() {return mImpl
;} 
 159         RefPointer
<Impl
> mImpl
; 
 164 // Event callback mix-in class 
 168 class RawModuleEvents 
{ 
 169         friend class ModuleImpl
; 
 171         virtual ~RawModuleEvents(); 
 173         virtual void notify(uint32 subService
, 
 174                 CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
) = 0; 
 177         static CSSM_RETURN 
sendNotify(const CSSM_GUID 
*, void *context
, uint32 subService
, 
 178                 CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
); 
 181 class ModuleEvents 
: public RawModuleEvents 
{ 
 183         virtual void insertion(uint32 subService
, CSSM_SERVICE_TYPE type
); 
 184         virtual void removal(uint32 subService
, CSSM_SERVICE_TYPE type
); 
 185         virtual void fault(uint32 subService
, CSSM_SERVICE_TYPE type
); 
 188         void notify(uint32 subService
, CSSM_SERVICE_TYPE type
, CSSM_MODULE_EVENT event
); 
 193 // A CSSM loadable module. 
 194 // You rarely directly interact with these objects, but if you need to, 
 197 class ModuleImpl 
: public ObjectImpl
, public HasGuid
 
 200         ModuleImpl(const Guid 
&guid
); 
 201         ModuleImpl(const Guid 
&guid
, const Cssm 
&session
); 
 202         virtual ~ModuleImpl(); 
 204         void load() { activate(); } 
 205         void unload() { deactivate(); } 
 206         bool isLoaded() const { return isActive(); } 
 208         Cssm 
session() const; 
 210         void appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback
, void *appNotifyCallbackCtx
); 
 211         void appNotifyCallback(RawModuleEvents 
*handler
); 
 217         CSSM_API_ModuleEventHandler mAppNotifyCallback
; 
 218         void *mAppNotifyCallbackCtx
; 
 221 class Module 
: public Object
 
 224         typedef ModuleImpl Impl
; 
 225         explicit Module(Impl 
*impl
) : Object(impl
) {} 
 226         Module() : Object(NULL
) {} // XXX This might break operator < 
 227         Module(const Guid 
&guid
) : Object(new Impl(guid
)) {} 
 228         Module(const Guid 
&guid
, const Cssm 
&session
) : Object(new Impl(guid
, session
)) {} 
 230         Impl 
*operator ->() const { return &impl
<Impl
>(); } 
 231         Impl 
&operator *() const { return impl
<Impl
>(); } 
 236 // An Attachment object. This is the base class of all typed attachment classes. 
 238 class AttachmentImpl 
: public ObjectImpl
 
 241         AttachmentImpl(const Guid 
&guid
, CSSM_SERVICE_TYPE subserviceType
); 
 242         AttachmentImpl(const Module 
&module, CSSM_SERVICE_TYPE subserviceType
); 
 243         //AttachmentImpl(... mds reference ...); 
 244         virtual ~AttachmentImpl(); 
 246         // Virtual so that subclasses can return there true mask. 
 247         virtual CSSM_SERVICE_MASK 
subserviceMask() const; 
 249         CSSM_SERVICE_TYPE 
subserviceType() const { return mSubserviceType
; } 
 250         CSSM_VERSION 
version() const { return mVersion
; } 
 251         void version(const CSSM_VERSION 
&v
) { mVersion 
= v
; } 
 252         uint32 
subserviceId() const { return mSubserviceId
; } 
 253         virtual void subserviceId(uint32 id
); 
 254         CSSM_ATTACH_FLAGS 
flags() const { return mAttachFlags
; } 
 255         void flags(CSSM_ATTACH_FLAGS f
) { mAttachFlags 
= f
; } 
 257         void attach() { activate(); } 
 258         void detach() { deactivate(); } 
 259         bool attached() const { return isActive(); } 
 261         Module 
module() const; 
 262         const Guid 
&guid() const { return module()->guid(); } 
 263         CSSM_MODULE_HANDLE 
handle() { attach(); return mHandle
; } 
 265         CssmSubserviceUid 
subserviceUid() const; 
 272         void make(CSSM_SERVICE_TYPE subserviceType
);    // common constructor 
 274         CSSM_MODULE_HANDLE mHandle
; 
 276         CSSM_SERVICE_TYPE mSubserviceType
;                              // set by constructor 
 277         CSSM_VERSION mVersion
; 
 278         uint32 mSubserviceId
; 
 279         CSSM_ATTACH_FLAGS mAttachFlags
; 
 281         CssmAllocatorMemoryFunctions mMemoryFunctions
;  // set on attach() 
 284 class Attachment 
: public Object
 
 287         typedef AttachmentImpl Impl
; 
 288         explicit Attachment(Impl 
*impl
) : Object(impl
) {} 
 289         Attachment(const Guid 
&guid
, CSSM_SERVICE_TYPE subserviceType
) 
 290         : Object(new Impl(guid
, subserviceType
)) {} 
 291         Attachment(const Module 
&module, CSSM_SERVICE_TYPE subserviceType
) 
 292         : Object(new Impl(module, subserviceType
)) {} 
 293         //Attachment(... mds reference ...); 
 295         Impl 
*operator ->() const { return &impl
<Impl
>(); } 
 296         Impl 
&operator *() const { return impl
<Impl
>(); } 
 301 // A CSSM session object. 
 302 // You usually only have one per program, or library, or what-not. 
 306 class CssmImpl 
: public ObjectImpl 
{ 
 307     class StandardCssm
; friend class StandardCssm
; 
 312         void init() { activate(); } 
 313         void terminate() { deactivate(); } 
 315         CSSM_PRIVILEGE_SCOPE 
scope() const { return mScope
; } 
 316         void scope(CSSM_PRIVILEGE_SCOPE sc
) { mScope 
= sc
; } 
 317         const Guid 
&callerGuid() const { return mCallerGuid
; } 
 318         void callerGuid(const CSSM_GUID 
&guid
) { mCallerGuid 
= Guid::overlay(guid
); } 
 320         Module 
autoModule(const Guid 
&guid
); 
 323         explicit CssmImpl(bool);                                // internal constructor 
 325         void setup();                                                   // constructor setup 
 331         // CSSM global configuration -- picked up on each Init 
 332         CSSM_VERSION mVersion
; 
 333         CSSM_PRIVILEGE_SCOPE mScope
; 
 336         // module repository: modules by guid (protected by self) 
 337         typedef map
<Guid
, Module
> ModuleMap
; 
 342         static Cssm 
standard(); 
 343         static void catchExit(); 
 346         static void atExitHandler(); 
 348     class StandardCssm 
: public Mutex 
{ 
 350         StandardCssm() : mCssm(NULL
) { } 
 352         void setCssm(CssmImpl 
*cssm
); 
 353         void unsetCssm(CssmImpl 
*cssm
); 
 357         RefPointer
<CssmImpl
> mCssm
; // 'Leaks' this object (in that it won't ever be deleted after creation), but 
 358                                     // there's no safe way to vend and re-create this object in a multi-threaded environment 
 359                                     // without an implementation of WeakRefPointer<>. 
 361     static ModuleNexus
<StandardCssm
> mStandard
; 
 364 class Cssm 
: public Object
 
 367         typedef CssmImpl Impl
; 
 368         explicit Cssm(Impl 
*impl
) : Object(impl
) {} 
 369         explicit Cssm() : Object(new Impl()) {} 
 371         Impl 
*operator ->() const { return &impl
<Impl
>(); } 
 372         Impl 
&operator *() const { return impl
<Impl
>(); } 
 374         static Cssm 
standard() { return CssmImpl::standard(); } 
 377 } // end namespace CssmClient  
 379 } // end namespace Security 
 381 #endif // _H_CDSA_CLIENT_CSSMCLIENT