1/* 2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. 3 * 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 8 * using this file. 9 * 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. 16 */ 17 18 19// 20// cssmclient - common client interface to CSSM and MDS 21// 22#ifndef _H_CDSA_CLIENT_CSSMCLIENT 23#define _H_CDSA_CLIENT_CSSMCLIENT 1 24 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> 30#include <map> 31 32namespace Security { 33namespace CssmClient { 34 35 36// 37// Forward declarations 38// 39class Cssm; 40class Module; 41class Attachment; 42 43 44// 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. 47// 48class HasGuid { 49public: 50 HasGuid(const Guid &guid) { mGuid = guid; } 51 HasGuid() { } 52 53 const Guid &guid() const { return mGuid; } 54 55protected: 56 void setGuid(const Guid &guid) { mGuid = guid; } 57 58private: 59 Guid mGuid; 60}; 61 62 63// 64// Exceptions are based on the CssmError utility class. We add our own class of client-side exceptions. 65// 66class Error : public CssmError { 67public: 68 Error(CSSM_RETURN err) : CssmError(err) { } 69 virtual const char *what () const throw(); 70 71 enum { 72 objectBusy = -1, 73 }; 74}; 75 76 77// 78// The CssmObject abstract class models features common to different Cssm objects. 79// It handles a tree hierarchy of objects (parent/children) safely. 80// 81class Object; 82 83class ObjectImpl : virtual public RefCount 84{ 85public: 86 explicit ObjectImpl(); // Constructor for Impl objects without a parent. 87 explicit ObjectImpl(const Object &parent); 88 virtual ~ObjectImpl(); 89 90 bool isActive() const { return mActive; } 91 92 virtual Allocator &allocator() const; 93 virtual void allocator(Allocator &alloc); 94 95 // Pointer comparison by default. Subclasses may override. 96 virtual bool operator <(const ObjectImpl &other) const; 97 virtual bool operator ==(const ObjectImpl &other) const; 98 99 static void check(CSSM_RETURN status); 100 bool isIdle() const { return mChildCount == 0; } 101 102protected: 103 bool mActive; // loaded, attached, etc. 104 RecursiveMutex mActivateMutex; 105 mutable Allocator *mAllocator; // allocator hierarchy (NULL => TBD) 106 107 template <class Obj> Obj parent() const 108 { assert(mParent); return Obj(static_cast<typename Obj::Impl *>(&(*mParent))); } 109 110 void addChild(); 111 void removeChild(); 112 113 // {de,}activate() assume you have locked *this 114 virtual void activate() = 0; 115 virtual void deactivate() = 0; 116 117private: 118 RefPointer<ObjectImpl> mParent; // parent object 119 AtomicCounter<uint32> mChildCount; 120}; 121 122 123class Object 124{ 125 friend class ObjectImpl; 126public: 127 typedef ObjectImpl Impl; 128 explicit Object(Impl *impl) : mImpl(impl) {} 129 130protected: 131 // @@@ CSPDL subclass breaks if the is a static_cast 132 template <class _Impl> _Impl &impl() const 133 { return dynamic_cast<_Impl &>(*mImpl); } 134 135public: 136 Impl *operator ->() const { return &(*mImpl); } 137 Impl &operator *() const { return *mImpl; } 138 139 // @@@ Why is this needed. DbCursor which inheirits from Object wants to call this. 140 template <class _Impl> _Impl &checkedImpl() const 141 { return dynamic_cast<_Impl &>(*mImpl); } 142 143 bool operator !() const { return !mImpl; } 144 operator bool() const { return mImpl; } 145 146 bool isActive() const { return mImpl && mImpl->isActive(); } 147 Allocator &allocator() const { return mImpl->allocator(); } 148 void release() { mImpl = NULL; } 149 150 bool operator <(const Object &other) const 151 { return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl < other.mImpl; } 152 bool operator ==(const Object &other) const 153 { return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl == other.mImpl; } 154 155 Impl* get() {return mImpl;} 156 157private: 158 RefPointer<Impl> mImpl; 159}; 160 161 162// 163// Event callback mix-in class 164// 165class ModuleImpl; 166 167class RawModuleEvents { 168 friend class ModuleImpl; 169public: 170 virtual ~RawModuleEvents(); 171 172 virtual void notify(uint32 subService, 173 CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) = 0; 174 175private: 176 static CSSM_RETURN sendNotify(const CSSM_GUID *, void *context, uint32 subService, 177 CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event); 178}; 179 180class ModuleEvents : public RawModuleEvents { 181public: 182 virtual void insertion(uint32 subService, CSSM_SERVICE_TYPE type); 183 virtual void removal(uint32 subService, CSSM_SERVICE_TYPE type); 184 virtual void fault(uint32 subService, CSSM_SERVICE_TYPE type); 185 186protected: 187 void notify(uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event); 188}; 189 190 191// 192// A CSSM loadable module. 193// You rarely directly interact with these objects, but if you need to, 194// here they are. 195// 196class ModuleImpl : public ObjectImpl, public HasGuid 197{ 198public: 199 ModuleImpl(const Guid &guid); 200 ModuleImpl(const Guid &guid, const Cssm &session); 201 virtual ~ModuleImpl(); 202 203 void load() { activate(); } 204 void unload() { deactivate(); } 205 bool isLoaded() const { return isActive(); } 206 207 Cssm session() const; 208 209 void appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx); 210 void appNotifyCallback(RawModuleEvents *handler); 211 212protected: 213 void activate(); 214 void deactivate(); 215 216 CSSM_API_ModuleEventHandler mAppNotifyCallback; 217 void *mAppNotifyCallbackCtx; 218}; 219 220class Module : public Object 221{ 222public: 223 typedef ModuleImpl Impl; 224 explicit Module(Impl *impl) : Object(impl) {} 225 Module() : Object(NULL) {} // XXX This might break operator < 226 Module(const Guid &guid) : Object(new Impl(guid)) {} 227 Module(const Guid &guid, const Cssm &session) : Object(new Impl(guid, session)) {} 228 229 Impl *operator ->() const { return &impl<Impl>(); } 230 Impl &operator *() const { return impl<Impl>(); } 231}; 232 233 234// 235// An Attachment object. This is the base class of all typed attachment classes. 236// 237class AttachmentImpl : public ObjectImpl 238{ 239public: 240 AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType); 241 AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType); 242 //AttachmentImpl(... mds reference ...); 243 virtual ~AttachmentImpl(); 244 245 // Virtual so that subclasses can return there true mask. 246 virtual CSSM_SERVICE_MASK subserviceMask() const; 247 248 CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; } 249 CSSM_VERSION version() const { return mVersion; } 250 void version(const CSSM_VERSION &v) { mVersion = v; } 251 uint32 subserviceId() const { return mSubserviceId; } 252 virtual void subserviceId(uint32 id); 253 CSSM_ATTACH_FLAGS flags() const { return mAttachFlags; } 254 void flags(CSSM_ATTACH_FLAGS f) { mAttachFlags = f; } 255 256 void attach() { activate(); } 257 void detach() { deactivate(); } 258 bool attached() const { return isActive(); } 259 260 Module module() const; 261 const Guid &guid() const { return module()->guid(); } 262 CSSM_MODULE_HANDLE handle() { attach(); return mHandle; } 263 264 CssmSubserviceUid subserviceUid() const; 265 266protected: 267 void activate(); 268 void deactivate(); 269 270private: 271 void make(CSSM_SERVICE_TYPE subserviceType); // common constructor 272 273 CSSM_MODULE_HANDLE mHandle; 274 275 CSSM_SERVICE_TYPE mSubserviceType; // set by constructor 276 CSSM_VERSION mVersion; 277 uint32 mSubserviceId; 278 CSSM_ATTACH_FLAGS mAttachFlags; 279 280 CssmAllocatorMemoryFunctions mMemoryFunctions; // set on attach() 281}; 282 283class Attachment : public Object 284{ 285public: 286 typedef AttachmentImpl Impl; 287 explicit Attachment(Impl *impl) : Object(impl) {} 288 Attachment(const Guid &guid, CSSM_SERVICE_TYPE subserviceType) 289 : Object(new Impl(guid, subserviceType)) {} 290 Attachment(const Module &module, CSSM_SERVICE_TYPE subserviceType) 291 : Object(new Impl(module, subserviceType)) {} 292 //Attachment(... mds reference ...); 293 294 Impl *operator ->() const { return &impl<Impl>(); } 295 Impl &operator *() const { return impl<Impl>(); } 296}; 297 298 299// 300// A CSSM session object. 301// You usually only have one per program, or library, or what-not. 302// 303class Cssm; 304 305class CssmImpl : public ObjectImpl { 306 class StandardCssm; friend class StandardCssm; 307public: 308 CssmImpl(); 309 virtual ~CssmImpl(); 310 311 void init() { activate(); } 312 void terminate() { deactivate(); } 313 314 CSSM_PRIVILEGE_SCOPE scope() const { return mScope; } 315 void scope(CSSM_PRIVILEGE_SCOPE sc) { mScope = sc; } 316 const Guid &callerGuid() const { return mCallerGuid; } 317 void callerGuid(const CSSM_GUID &guid) { mCallerGuid = Guid::overlay(guid); } 318 319 Module autoModule(const Guid &guid); 320 321protected: 322 explicit CssmImpl(bool); // internal constructor 323 324 void setup(); // constructor setup 325 326 void activate(); 327 void deactivate(); 328 329private: 330 // CSSM global configuration -- picked up on each Init 331 CSSM_VERSION mVersion; 332 CSSM_PRIVILEGE_SCOPE mScope; 333 Guid mCallerGuid; 334 335 // module repository: modules by guid (protected by self) 336 typedef map<Guid, Module> ModuleMap; 337 ModuleMap moduleMap; 338 Mutex mapLock; 339 340public: 341 static Cssm standard(); 342 static void catchExit(); 343 344private: 345 static void atExitHandler(); 346 347 class StandardCssm : public Mutex { 348 public: 349 StandardCssm() : mCssm(NULL) { } 350 ~StandardCssm(); 351 void setCssm(CssmImpl *cssm); 352 void unsetCssm(CssmImpl *cssm); 353 CssmImpl *get(); 354 355 private: 356 CssmImpl *mCssm; 357 }; 358 static ModuleNexus<StandardCssm> mStandard; 359}; 360 361class Cssm : public Object 362{ 363public: 364 typedef CssmImpl Impl; 365 explicit Cssm(Impl *impl) : Object(impl) {} 366 explicit Cssm() : Object(new Impl()) {} 367 368 Impl *operator ->() const { return &impl<Impl>(); } 369 Impl &operator *() const { return impl<Impl>(); } 370 371 static Cssm standard() { return CssmImpl::standard(); } 372}; 373 374} // end namespace CssmClient 375 376} // end namespace Security 377 378#endif // _H_CDSA_CLIENT_CSSMCLIENT 379