]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cssm/lib/attachment.h
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_cssm / lib / attachment.h
1 /*
2 * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // attachment - CSSM module attachment objects
27 //
28 #ifndef _H_ATTACHMENT
29 #define _H_ATTACHMENT
30
31 #include "cssmint.h"
32 #include "module.h"
33 #include <security_cdsa_utilities/handleobject.h>
34 #include <security_cdsa_utilities/cssmalloc.h>
35
36
37 //
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.
50 //
51 class Attachment : public HandleObject, // has a handle
52 public CssmMemoryFunctionsAllocator, // is an allocator
53 public CountingMutex { // is a counting lock
54 NOCOPY(Attachment)
55 public:
56 Attachment(Module *theModule,
57 const CSSM_VERSION &version,
58 uint32 subserviceId,
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();
64
65 Module &module;
66
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; }
73
74 bool isThreadSafe() const { return module.isThreadSafe(); }
75
76 // service a symbol table inquiry against our attachment
77 virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR *FunctionTable,
78 uint32 NumFunctions) = 0;
79
80 // terminate the live attachment and prepare to die
81 void detach(bool isLocked);
82
83 template <class Sub> friend Sub &enterAttachment(CSSM_HANDLE);
84
85 // need to redefine lock/trylock to implement HandleObject protocol
86 void lock() { CountingMutex::lock(); }
87 bool tryLock() { return CountingMutex::tryLock(); }
88
89 private:
90 bool mIsActive; // successfully attached to plugin
91
92 uint32 mSubserviceId; // subservice ID in use
93 CSSM_SERVICE_TYPE mSubserviceType; // service type
94
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
99
100 protected:
101 CSSM_MODULE_FUNCS *spiFunctionTable; // entry table as returned by plugin on attach
102
103 private:
104 CSSM_UPCALLS upcalls; // upcall functions for our module
105
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,
113 CSSM_GUID_PTR Guid,
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);
122 };
123
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)
129 {
130 AttachmentSubclass &attachment = HandleObject::findAndLock<AttachmentSubclass>(h, CSSMERR_CSSM_INVALID_ADDIN_HANDLE);
131 attachment.finishEnter();
132 return attachment;
133 }
134
135
136 //
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.
144 //
145 template <CSSM_SERVICE_TYPE type, class FunctionTable>
146 class StandardAttachment : public Attachment {
147 public:
148 typedef map<const char *, unsigned int> NameMap;
149
150 StandardAttachment(Module *theModule,
151 const NameMap &names,
152 const CSSM_VERSION &version,
153 uint32 subserviceId,
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),
160 nameMap(names)
161 {
162 try {
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));
169 } catch (...) {
170 // we are attached to the plugin, so tell it the show is off
171 detach(false);
172 throw;
173 }
174 }
175
176 void resolveSymbols(CSSM_FUNC_NAME_ADDR *inFunctionTable,
177 uint32 NumFunctions)
178 {
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);
183 }
184 }
185
186 FunctionTable downcalls;
187
188 CSSM_PROC_ADDR downcallNumber(uint32 index) const
189 {
190 assert(index < sizeof(downcalls) / sizeof(CSSM_PROC_ADDR));
191 return reinterpret_cast<const CSSM_PROC_ADDR *>(&downcalls)[index];
192 }
193
194 private:
195 const NameMap &nameMap;
196 };
197
198
199 #endif //_H_ATTACHMENT