]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_cdsa_client/lib/cssmclient.h
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_cdsa_client / lib / cssmclient.h
diff --git a/libsecurity_cdsa_client/lib/cssmclient.h b/libsecurity_cdsa_client/lib/cssmclient.h
new file mode 100644 (file)
index 0000000..b6b2f32
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+
+//
+// cssmclient - common client interface to CSSM and MDS
+//
+#ifndef _H_CDSA_CLIENT_CSSMCLIENT
+#define _H_CDSA_CLIENT_CSSMCLIENT  1
+
+#include <security_utilities/threading.h>
+#include <security_utilities/globalizer.h>
+#include <security_utilities/refcount.h>
+#include <security_cdsa_utilities/cssmalloc.h>
+#include <security_cdsa_utilities/cssmpods.h>
+#include <map>
+
+namespace Security {
+namespace CssmClient {
+
+
+//
+// Forward declarations
+//
+class Cssm;
+class Module;
+class Attachment;
+
+
+//
+// An mixin for objects that have (store) GUIDs.
+// The GUID value is meant to be set-once constant, and can be lock-handled accordingly.
+//
+class HasGuid {
+public:
+       HasGuid(const Guid &guid) { mGuid = guid; }
+       HasGuid() { }
+       
+       const Guid &guid() const { return mGuid; }
+
+protected:
+       void setGuid(const Guid &guid) { mGuid = guid; }
+       
+private:
+       Guid mGuid;
+};
+
+
+//
+// Exceptions are based on the CssmError utility class. We add our own class of client-side exceptions.
+//
+class Error : public CssmError {
+public:
+       Error(CSSM_RETURN err) : CssmError(err) { }
+       virtual const char *what () const throw();
+       
+       enum {
+               objectBusy = -1,
+       };
+};
+
+
+//
+// The CssmObject abstract class models features common to different Cssm objects.
+// It handles a tree hierarchy of objects (parent/children) safely.
+//
+class Object;
+
+class ObjectImpl : virtual public RefCount
+{
+public:
+       explicit ObjectImpl(); // Constructor for Impl objects without a parent.
+       explicit ObjectImpl(const Object &parent);
+       virtual ~ObjectImpl();
+
+       bool isActive() const { return mActive; }
+
+       virtual Allocator &allocator() const;
+       virtual void allocator(Allocator &alloc);
+
+       // Pointer comparison by default.  Subclasses may override.
+       virtual bool operator <(const ObjectImpl &other) const;
+       virtual bool operator ==(const ObjectImpl &other) const;
+
+       static void check(CSSM_RETURN status);
+
+protected:
+       bool mActive;                                   // loaded, attached, etc.
+       mutable Allocator *mAllocator; // allocator hierarchy (NULL => TBD)
+       
+       template <class Obj> Obj parent() const
+       { assert(mParent); return Obj(static_cast<typename Obj::Impl *>(&(*mParent))); }
+
+       void addChild();
+       void removeChild();
+       bool isIdle() const { return mChildCount == 0; }
+
+       // {de,}activate() assume you have locked *this
+       virtual void activate() = 0;
+       virtual void deactivate() = 0;
+
+private:
+       RefPointer<ObjectImpl> mParent;         // parent object
+       AtomicCounter<uint32> mChildCount;
+};
+
+
+class Object
+{
+       friend class ObjectImpl;
+public:
+       typedef ObjectImpl Impl;
+       explicit Object(Impl *impl) : mImpl(impl) {}
+
+protected:
+       // @@@ CSPDL subclass breaks if the is a static_cast
+       template <class _Impl> _Impl &impl() const
+       { return dynamic_cast<_Impl &>(*mImpl); }
+
+public:
+       Impl *operator ->() const { return &(*mImpl); }
+       Impl &operator *() const { return *mImpl; }
+
+       // @@@ Why is this needed.  DbCursor which inheirits from Object wants to call this.
+       template <class _Impl> _Impl &checkedImpl() const
+       { return dynamic_cast<_Impl &>(*mImpl); }
+
+       bool operator !() const { return !mImpl; }
+       operator bool() const { return mImpl; }
+    
+    bool isActive() const                              { return mImpl && mImpl->isActive(); }
+    Allocator &allocator() const       { return mImpl->allocator(); }
+       void release()                                          { mImpl = NULL; }
+
+       bool operator <(const Object &other) const
+       { return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl < other.mImpl; }
+       bool operator ==(const Object &other) const
+       { return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl == other.mImpl; }
+
+private:
+       RefPointer<Impl> mImpl;
+};
+
+
+//
+// Event callback mix-in class
+//
+class ModuleImpl;
+
+class RawModuleEvents {
+       friend class ModuleImpl;
+public:
+       virtual ~RawModuleEvents();
+
+       virtual void notify(uint32 subService,
+               CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) = 0;
+
+private:
+       static CSSM_RETURN sendNotify(const CSSM_GUID *, void *context, uint32 subService,
+               CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event);
+};
+
+class ModuleEvents : public RawModuleEvents {
+public:
+       virtual void insertion(uint32 subService, CSSM_SERVICE_TYPE type);
+       virtual void removal(uint32 subService, CSSM_SERVICE_TYPE type);
+       virtual void fault(uint32 subService, CSSM_SERVICE_TYPE type);
+
+protected:
+       void notify(uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event);
+};
+
+
+//
+// A CSSM loadable module.
+// You rarely directly interact with these objects, but if you need to,
+// here they are.
+//
+class ModuleImpl : public ObjectImpl, public HasGuid
+{
+public:
+       ModuleImpl(const Guid &guid);
+       ModuleImpl(const Guid &guid, const Cssm &session);
+       virtual ~ModuleImpl();
+       
+       void load() { activate(); }
+       void unload() { deactivate(); }
+       bool isLoaded() const { return isActive(); }
+       
+       Cssm session() const;
+
+       void appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx);
+       void appNotifyCallback(RawModuleEvents *handler);
+
+protected:
+       void activate();
+       void deactivate();
+
+       CSSM_API_ModuleEventHandler mAppNotifyCallback;
+       void *mAppNotifyCallbackCtx;
+};
+
+class Module : public Object
+{
+public:
+       typedef ModuleImpl Impl;
+       explicit Module(Impl *impl) : Object(impl) {}
+       Module() : Object(NULL) {} // XXX This might break operator <
+       Module(const Guid &guid) : Object(new Impl(guid)) {}
+       Module(const Guid &guid, const Cssm &session) : Object(new Impl(guid, session)) {}
+
+       Impl *operator ->() const { return &impl<Impl>(); }
+       Impl &operator *() const { return impl<Impl>(); }
+};
+
+
+//
+// An Attachment object. This is the base class of all typed attachment classes.
+//
+class AttachmentImpl : public ObjectImpl
+{
+public:
+       AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType);
+       AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType);
+       //AttachmentImpl(... mds reference ...);
+       virtual ~AttachmentImpl();
+
+       // Virtual so that subclasses can return there true mask.
+       virtual CSSM_SERVICE_MASK subserviceMask() const;
+
+       CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; }
+       CSSM_VERSION version() const { return mVersion; }
+       void version(const CSSM_VERSION &v) { mVersion = v; }
+       uint32 subserviceId() const { return mSubserviceId; }
+       virtual void subserviceId(uint32 id);
+       CSSM_ATTACH_FLAGS flags() const { return mAttachFlags; }
+       void flags(CSSM_ATTACH_FLAGS f) { mAttachFlags = f; }
+
+       void attach() { activate(); }
+       void detach() { deactivate(); }
+       bool attached() const { return isActive(); }
+
+       Module module() const;
+       const Guid &guid() const { return module()->guid(); }
+       CSSM_MODULE_HANDLE handle() { attach(); return mHandle; }
+
+       CssmSubserviceUid subserviceUid() const;
+
+protected:
+       void activate();
+       void deactivate();
+
+private:
+       void make(CSSM_SERVICE_TYPE subserviceType);    // common constructor
+
+       CSSM_MODULE_HANDLE mHandle;
+
+       CSSM_SERVICE_TYPE mSubserviceType;                              // set by constructor
+       CSSM_VERSION mVersion;
+       uint32 mSubserviceId;
+       CSSM_ATTACH_FLAGS mAttachFlags;
+
+       CssmAllocatorMemoryFunctions mMemoryFunctions;  // set on attach()
+};
+
+class Attachment : public Object
+{
+public:
+       typedef AttachmentImpl Impl;
+       explicit Attachment(Impl *impl) : Object(impl) {}
+       Attachment(const Guid &guid, CSSM_SERVICE_TYPE subserviceType)
+       : Object(new Impl(guid, subserviceType)) {}
+       Attachment(const Module &module, CSSM_SERVICE_TYPE subserviceType)
+       : Object(new Impl(module, subserviceType)) {}
+       //Attachment(... mds reference ...);
+
+       Impl *operator ->() const { return &impl<Impl>(); }
+       Impl &operator *() const { return impl<Impl>(); }
+};
+
+
+//
+// A CSSM session object.
+// You usually only have one per program, or library, or what-not.
+//
+class Cssm;
+
+class CssmImpl : public ObjectImpl {
+    class StandardCssm; friend class StandardCssm;
+public:
+       CssmImpl();
+       virtual ~CssmImpl();
+
+       void init() { activate(); }
+       void terminate() { deactivate(); }
+
+       CSSM_PRIVILEGE_SCOPE scope() const { return mScope; }
+       void scope(CSSM_PRIVILEGE_SCOPE sc) { mScope = sc; }
+       const Guid &callerGuid() const { return mCallerGuid; }
+       void callerGuid(const CSSM_GUID &guid) { mCallerGuid = Guid::overlay(guid); }
+
+       Module autoModule(const Guid &guid);
+    
+protected:
+       explicit CssmImpl(bool);                                // internal constructor
+
+       void setup();                                                   // constructor setup
+
+       void activate();
+       void deactivate();
+
+private:
+       // CSSM global configuration -- picked up on each Init
+       CSSM_VERSION mVersion;
+       CSSM_PRIVILEGE_SCOPE mScope;
+       Guid mCallerGuid;
+
+       // module repository: modules by guid (protected by self)
+       typedef map<Guid, Module> ModuleMap;
+       ModuleMap moduleMap;
+       Mutex mapLock;
+
+public:
+       static Cssm standard();
+       static void catchExit();
+
+private:
+       static void atExitHandler();
+    
+    class StandardCssm : public Mutex {
+    public:
+        StandardCssm() : mCssm(NULL) { }
+        ~StandardCssm();
+        void setCssm(CssmImpl *cssm);
+        void unsetCssm(CssmImpl *cssm);
+        CssmImpl *get();
+        
+    private:
+        CssmImpl *mCssm;
+    };
+    static ModuleNexus<StandardCssm> mStandard;
+};
+
+class Cssm : public Object
+{
+public:
+       typedef CssmImpl Impl;
+       explicit Cssm(Impl *impl) : Object(impl) {}
+       explicit Cssm() : Object(new Impl()) {}
+
+       Impl *operator ->() const { return &impl<Impl>(); }
+       Impl &operator *() const { return impl<Impl>(); }
+
+       static Cssm standard() { return CssmImpl::standard(); }
+};
+
+} // end namespace CssmClient 
+
+} // end namespace Security
+
+#endif // _H_CDSA_CLIENT_CSSMCLIENT