]> git.saurik.com Git - apple/security.git/blob - cdsa/cssm/attachment.h
Security-164.1.tar.gz
[apple/security.git] / cdsa / cssm / attachment.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, 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 // attachment - CSSM module attachment objects
21 //
22 #ifndef _H_ATTACHMENT
23 #define _H_ATTACHMENT
24
25 #include "cssmint.h"
26 #include "module.h"
27 #include <Security/handleobject.h>
28 #include <Security/cssmalloc.h>
29
30 #ifdef _CPP_ATTACHMENT
31 # pragma export on
32 #endif
33
34
35 //
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.
48 //
49 class Attachment : public HandleObject, // has a handle
50 public CssmMemoryFunctionsAllocator, // is an allocator
51 public CountingMutex { // is a counting lock
52 NOCOPY(Attachment)
53 public:
54 Attachment(Module *theModule,
55 const CSSM_VERSION &version,
56 uint32 subserviceId,
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();
62
63 Module &module;
64
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; }
71
72 bool isThreadSafe() const { return module.isThreadSafe(); }
73
74 // service a symbol table inquiry against our attachment
75 virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR *FunctionTable,
76 uint32 NumFunctions) = 0;
77
78 // terminate the live attachment and prepare to die
79 void detach(bool isLocked);
80
81 template <class Sub> friend Sub &enterAttachment(CSSM_HANDLE);
82
83 // need to redefine lock/trylock to implement HandleObject protocol
84 void lock() { CountingMutex::lock(); }
85 bool tryLock() { return CountingMutex::tryLock(); }
86
87 private:
88 bool mIsActive; // successfully attached to plugin
89
90 uint32 mSubserviceId; // subservice ID in use
91 CSSM_SERVICE_TYPE mSubserviceType; // service type
92
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
97
98 protected:
99 CSSM_MODULE_FUNCS *spiFunctionTable; // entry table as returned by plugin on attach
100
101 private:
102 CSSM_UPCALLS upcalls; // upcall functions for our module
103
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,
111 CSSM_GUID_PTR Guid,
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);
120 };
121
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)
127 {
128 AttachmentSubclass &attachment = findHandleAndLock<AttachmentSubclass>(h);
129 attachment.finishEnter();
130 return attachment;
131 }
132
133
134 //
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.
142 //
143 template <CSSM_SERVICE_TYPE type, class FunctionTable>
144 class StandardAttachment : public Attachment {
145 public:
146 typedef map<const char *, unsigned int> NameMap;
147
148 StandardAttachment(Module *theModule,
149 const NameMap &names,
150 const CSSM_VERSION &version,
151 uint32 subserviceId,
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),
158 nameMap(names)
159 {
160 try {
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));
167 } catch (...) {
168 // we are attached to the plugin, so tell it the show is off
169 detach(false);
170 throw;
171 }
172 }
173
174 void resolveSymbols(CSSM_FUNC_NAME_ADDR *inFunctionTable,
175 uint32 NumFunctions)
176 {
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);
181 }
182 }
183
184 FunctionTable downcalls;
185
186 CSSM_PROC_ADDR downcallNumber(uint32 index) const
187 {
188 assert(index < sizeof(downcalls) / sizeof(CSSM_PROC_ADDR));
189 return reinterpret_cast<const CSSM_PROC_ADDR *>(&downcalls)[index];
190 }
191
192 private:
193 const NameMap &nameMap;
194 };
195
196 #ifdef _CPP_ATTACHMENT
197 # pragma export off
198 #endif
199
200
201 #endif //_H_ATTACHMENT