2 * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // attachment - CSSM module attachment objects
33 #include <security_cdsa_utilities/handleobject.h>
34 #include <security_cdsa_utilities/cssmalloc.h>
38 // This type represents a single Attachment of any kind.
39 // Attachments are formed by the CSSM_ModuleAttach call and represent a "session"
40 // between a caller client and a particular plugin module. Any number of attachments
41 // can exist for a particular caller and a particular module.
42 // Attachment is an abstract class. You must subclass it to implement a concrete
43 // type of plugin. For the standard ones, see the end of this header.
44 // Key recovery does not use Attachments.
45 // EMMs are not Attachments, but the plugins they manage are.
46 // And yes, an Attachment *is* a lock. The API transition layer functions need
47 // to lock Attachments from the "outside", so there's no point in being coy about it.
48 // Locking the Attachment is equivalent to locking all its members except for
49 // instance-constant ones.
51 class Attachment
: public HandleObject
, // has a handle
52 public CssmMemoryFunctionsAllocator
, // is an allocator
53 public CountingMutex
{ // is a counting lock
56 Attachment(Module
*theModule
,
57 const CSSM_VERSION
&version
,
59 CSSM_SERVICE_TYPE subserviceType
,
60 const CSSM_API_MEMORY_FUNCS
&memoryOps
,
61 CSSM_ATTACH_FLAGS attachFlags
,
62 CSSM_KEY_HIERARCHY keyHierarchy
);
63 virtual ~Attachment();
67 // feature inquiries. These features are constant for the life of the Attachment
68 const Guid
&myGuid() const { return module.myGuid(); }
69 CSSM_SERVICE_TYPE
subserviceType() const { return mSubserviceType
; }
70 uint32
subserviceId() const { return mSubserviceId
; }
71 const CSSM_VERSION
&pluginVersion() const { return mVersion
; }
72 CSSM_ATTACH_FLAGS
attachFlags() const { return mAttachFlags
; }
74 bool isThreadSafe() const { return module.isThreadSafe(); }
76 // service a symbol table inquiry against our attachment
77 virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR
*FunctionTable
,
78 uint32 NumFunctions
) = 0;
80 // terminate the live attachment and prepare to die
81 void detach(bool isLocked
);
83 template <class Sub
> friend Sub
&enterAttachment(CSSM_HANDLE
);
85 // need to redefine lock/trylock to implement HandleObject protocol
86 void lock() { CountingMutex::lock(); }
87 bool tryLock() { return CountingMutex::tryLock(); }
90 bool mIsActive
; // successfully attached to plugin
92 uint32 mSubserviceId
; // subservice ID in use
93 CSSM_SERVICE_TYPE mSubserviceType
; // service type
95 // how we were created
96 CSSM_VERSION mVersion
; // plugin version requested
97 CSSM_ATTACH_FLAGS mAttachFlags
; // attach flags requested
98 CSSM_KEY_HIERARCHY mKeyHierarchy
; // key hierarchy verified
101 CSSM_MODULE_FUNCS
*spiFunctionTable
; // entry table as returned by plugin on attach
104 CSSM_UPCALLS upcalls
; // upcall functions for our module
106 // upcall implementors - these are handed to the plugin in `upcalls'
107 static void *upcallMalloc(CSSM_HANDLE handle
, size_t size
);
108 static void upcallFree(CSSM_HANDLE handle
, void *mem
);
109 static void *upcallRealloc(CSSM_HANDLE handle
, void *mem
, size_t size
);
110 static void *upcallCalloc(CSSM_HANDLE handle
, size_t num
, size_t size
);
111 static CSSM_RETURN
upcallCcToHandle(CSSM_CC_HANDLE handle
, CSSM_MODULE_HANDLE
*modHandle
);
112 static CSSM_RETURN
upcallGetModuleInfo(CSSM_MODULE_HANDLE Module
,
114 CSSM_VERSION_PTR Version
,
115 uint32
*SubServiceId
,
116 CSSM_SERVICE_TYPE
*SubServiceType
,
117 CSSM_ATTACH_FLAGS
*AttachFlags
,
118 CSSM_KEY_HIERARCHY
*KeyHierarchy
,
119 CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs
,
120 CSSM_FUNC_NAME_ADDR_PTR FunctionTable
,
121 uint32 NumFunctions
);
124 // this should be a member template, but egcs barfs on its invocation
125 // @@@ pass module code in to get better "invalid handle" diag?
126 // @@@ or use template specializations here?
127 template <class AttachmentSubclass
>
128 inline AttachmentSubclass
&enterAttachment(CSSM_HANDLE h
)
130 AttachmentSubclass
&attachment
= HandleObject::findAndLock
<AttachmentSubclass
>(h
, CSSMERR_CSSM_INVALID_ADDIN_HANDLE
);
131 attachment
.finishEnter();
137 // For the standard attachment types, function dispatch to the plugin
138 // is done based on the CSSM_SPI_xxx_FUNCS structures describing the
139 // types and ordering of entry points. The StandardAttachment class
140 // implements this by holding a copy of these tables for the use of
141 // the transition layer.
142 // You are free to subclass from Attachment directly if that makes better
143 // sense to your kind of plugin.
145 template <CSSM_SERVICE_TYPE type
, class FunctionTable
>
146 class StandardAttachment
: public Attachment
{
148 typedef map
<const char *, unsigned int> NameMap
;
150 StandardAttachment(Module
*theModule
,
151 const NameMap
&names
,
152 const CSSM_VERSION
&version
,
154 CSSM_SERVICE_TYPE subserviceType
,
155 const CSSM_API_MEMORY_FUNCS
&memoryOps
,
156 CSSM_ATTACH_FLAGS attachFlags
,
157 CSSM_KEY_HIERARCHY keyHierarchy
)
158 : Attachment(theModule
, version
, subserviceId
, subserviceType
,
159 memoryOps
, attachFlags
, keyHierarchy
),
163 if (spiFunctionTable
->NumberOfServiceFuncs
<
164 sizeof(FunctionTable
) / sizeof(CSSM_PROC_ADDR
))
165 CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE
);
166 // tolerate a table that's TOO large - perhaps it's a newer version
167 // @@@ with the new spec, we could just store the pointer
168 memcpy(&downcalls
, spiFunctionTable
->ServiceFuncs
, sizeof(downcalls
));
170 // we are attached to the plugin, so tell it the show is off
176 void resolveSymbols(CSSM_FUNC_NAME_ADDR
*inFunctionTable
,
179 for (unsigned n
= 0; n
< NumFunctions
; n
++) {
180 NameMap::const_iterator it
= nameMap
.find(inFunctionTable
[n
].Name
);
181 inFunctionTable
[n
].Address
=
182 (it
== nameMap
.end()) ? NULL
: downcallNumber(it
->second
);
186 FunctionTable downcalls
;
188 CSSM_PROC_ADDR
downcallNumber(uint32 index
) const
190 assert(index
< sizeof(downcalls
) / sizeof(CSSM_PROC_ADDR
));
191 return reinterpret_cast<const CSSM_PROC_ADDR
*>(&downcalls
)[index
];
195 const NameMap
&nameMap
;
199 #endif //_H_ATTACHMENT