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
, false) { }
69 virtual const char *what () const _NOEXCEPT
;
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