2 * Copyright (c) 2000-2001 Apple Computer, 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 // attachment - CSSM module attachment objects
27 #include <Security/handleobject.h>
28 #include <Security/cssmalloc.h>
30 #ifdef _CPP_ATTACHMENT
36 // This type represents a single Attachment of any kind.
37 // Attachments are formed by the CSSM_ModuleAttach call and represent a "session"
38 // between a caller client and a particular plugin module. Any number of attachments
39 // can exist for a particular caller and a particular module.
40 // Attachment is an abstract class. You must subclass it to implement a concrete
41 // type of plugin. For the standard ones, see the end of this header.
42 // Key recovery does not use Attachments.
43 // EMMs are not Attachments, but the plugins they manage are.
44 // And yes, an Attachment *is* a lock. The API transition layer functions need
45 // to lock Attachments from the "outside", so there's no point in being coy about it.
46 // Locking the Attachment is equivalent to locking all its members except for
47 // instance-constant ones.
49 class Attachment
: public HandleObject
, // has a handle
50 public CssmMemoryFunctionsAllocator
, // is an allocator
51 public CountingMutex
{ // is a counting lock
54 Attachment(Module
*theModule
,
55 const CSSM_VERSION
&version
,
57 CSSM_SERVICE_TYPE subserviceType
,
58 const CSSM_API_MEMORY_FUNCS
&memoryOps
,
59 CSSM_ATTACH_FLAGS attachFlags
,
60 CSSM_KEY_HIERARCHY keyHierarchy
);
61 virtual ~Attachment();
65 // feature inquiries. These features are constant for the life of the Attachment
66 const Guid
&myGuid() const { return module.myGuid(); }
67 CSSM_SERVICE_TYPE
subserviceType() const { return mSubserviceType
; }
68 uint32
subserviceId() const { return mSubserviceId
; }
69 const CSSM_VERSION
&pluginVersion() const { return mVersion
; }
70 CSSM_ATTACH_FLAGS
attachFlags() const { return mAttachFlags
; }
72 bool isThreadSafe() const { return module.isThreadSafe(); }
74 // service a symbol table inquiry against our attachment
75 virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR
*FunctionTable
,
76 uint32 NumFunctions
) = 0;
78 // terminate the live attachment and prepare to die
79 void detach(bool isLocked
);
81 template <class Sub
> friend Sub
&enterAttachment(CSSM_HANDLE
);
83 // need to redefine lock/trylock to implement HandleObject protocol
84 void lock() { CountingMutex::lock(); }
85 bool tryLock() { return CountingMutex::tryLock(); }
88 bool mIsActive
; // successfully attached to plugin
90 uint32 mSubserviceId
; // subservice ID in use
91 CSSM_SERVICE_TYPE mSubserviceType
; // service type
93 // how we were created
94 CSSM_VERSION mVersion
; // plugin version requested
95 CSSM_ATTACH_FLAGS mAttachFlags
; // attach flags requested
96 CSSM_KEY_HIERARCHY mKeyHierarchy
; // key hierarchy verified
99 CSSM_MODULE_FUNCS
*spiFunctionTable
; // entry table as returned by plugin on attach
102 CSSM_UPCALLS upcalls
; // upcall functions for our module
104 // upcall implementors - these are handed to the plugin in `upcalls'
105 static void *upcallMalloc(CSSM_HANDLE handle
, uint32 size
);
106 static void upcallFree(CSSM_HANDLE handle
, void *mem
);
107 static void *upcallRealloc(CSSM_HANDLE handle
, void *mem
,uint32 size
);
108 static void *upcallCalloc(CSSM_HANDLE handle
, uint32 num
, uint32 size
);
109 static CSSM_RETURN
upcallCcToHandle(CSSM_CC_HANDLE handle
, CSSM_MODULE_HANDLE
*modHandle
);
110 static CSSM_RETURN
upcallGetModuleInfo(CSSM_MODULE_HANDLE Module
,
112 CSSM_VERSION_PTR Version
,
113 uint32
*SubServiceId
,
114 CSSM_SERVICE_TYPE
*SubServiceType
,
115 CSSM_ATTACH_FLAGS
*AttachFlags
,
116 CSSM_KEY_HIERARCHY
*KeyHierarchy
,
117 CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs
,
118 CSSM_FUNC_NAME_ADDR_PTR FunctionTable
,
119 uint32 NumFunctions
);
122 // this should be a member template, but egcs barfs on its invocation
123 // @@@ pass module code in to get better "invalid handle" diag?
124 // @@@ or use template specializations here?
125 template <class AttachmentSubclass
>
126 inline AttachmentSubclass
&enterAttachment(CSSM_HANDLE h
)
128 AttachmentSubclass
&attachment
= findHandleAndLock
<AttachmentSubclass
>(h
);
129 attachment
.finishEnter();
135 // For the standard attachment types, function dispatch to the plugin
136 // is done based on the CSSM_SPI_xxx_FUNCS structures describing the
137 // types and ordering of entry points. The StandardAttachment class
138 // implements this by holding a copy of these tables for the use of
139 // the transition layer.
140 // You are free to subclass from Attachment directly if that makes better
141 // sense to your kind of plugin.
143 template <CSSM_SERVICE_TYPE type
, class FunctionTable
>
144 class StandardAttachment
: public Attachment
{
146 typedef map
<const char *, unsigned int> NameMap
;
148 StandardAttachment(Module
*theModule
,
149 const NameMap
&names
,
150 const CSSM_VERSION
&version
,
152 CSSM_SERVICE_TYPE subserviceType
,
153 const CSSM_API_MEMORY_FUNCS
&memoryOps
,
154 CSSM_ATTACH_FLAGS attachFlags
,
155 CSSM_KEY_HIERARCHY keyHierarchy
)
156 : Attachment(theModule
, version
, subserviceId
, subserviceType
,
157 memoryOps
, attachFlags
, keyHierarchy
),
161 if (spiFunctionTable
->NumberOfServiceFuncs
<
162 sizeof(FunctionTable
) / sizeof(CSSM_PROC_ADDR
))
163 CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE
);
164 // tolerate a table that's TOO large - perhaps it's a newer version
165 // @@@ with the new spec, we could just store the pointer
166 memcpy(&downcalls
, spiFunctionTable
->ServiceFuncs
, sizeof(downcalls
));
168 // we are attached to the plugin, so tell it the show is off
174 void resolveSymbols(CSSM_FUNC_NAME_ADDR
*inFunctionTable
,
177 for (unsigned n
= 0; n
< NumFunctions
; n
++) {
178 NameMap::const_iterator it
= nameMap
.find(inFunctionTable
[n
].Name
);
179 inFunctionTable
[n
].Address
=
180 (it
== nameMap
.end()) ? NULL
: downcallNumber(it
->second
);
184 FunctionTable downcalls
;
186 CSSM_PROC_ADDR
downcallNumber(uint32 index
) const
188 assert(index
< sizeof(downcalls
) / sizeof(CSSM_PROC_ADDR
));
189 return reinterpret_cast<const CSSM_PROC_ADDR
*>(&downcalls
)[index
];
193 const NameMap
&nameMap
;
196 #ifdef _CPP_ATTACHMENT
201 #endif //_H_ATTACHMENT