]> git.saurik.com Git - apple/security.git/blob - libsecurity_cssm/lib/manager.cpp
Security-55471.14.4.tar.gz
[apple/security.git] / libsecurity_cssm / lib / manager.cpp
1 /*
2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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 // manager - CSSM manager/supervisor objects.
27 //
28 #include "manager.h"
29 #include "module.h"
30 #include <security_utilities/debugging.h>
31
32
33 //
34 // Constructing a CssmManager instance.
35 // This does almost nothing - the actual intialization happens in the initialize() method.
36 //
37 CssmManager::CssmManager()
38 {
39 initCount = 0; // not yet initialized
40 }
41
42 CssmManager::~CssmManager()
43 {
44 if (initCount > 0)
45 secdebug("cssm", "CSSM forcibly shutting down");
46 }
47
48
49 //
50 // CSSM initialization.
51 // THREADS: This function must run in an uncontested environment.
52 //
53 void CssmManager::initialize (const CSSM_VERSION &version,
54 CSSM_PRIVILEGE_SCOPE scope,
55 const Guid &callerGuid,
56 CSSM_KEY_HIERARCHY keyHierarchy,
57 CSSM_PVC_MODE &pvcPolicy)
58 {
59 StLock<Mutex> _(mLock);
60
61 // check version first
62 checkVersion(version);
63
64 if (initCount) {
65 // re-initialization processing as per CSSM spec
66 if (pvcPolicy != mPvcPolicy) {
67 pvcPolicy = mPvcPolicy; // return old value
68 CssmError::throwMe(CSSMERR_CSSM_PVC_ALREADY_CONFIGURED);
69 }
70 initCount++;
71 secdebug("cssm", "re-initializing CSSM (%d levels)", initCount);
72 return;
73 }
74
75 // we don't support thread scope privileges
76 if (scope == CSSM_PRIVILEGE_SCOPE_THREAD)
77 CssmError::throwMe(CSSMERR_CSSM_SCOPE_NOT_SUPPORTED);
78
79 // keep the init arguments for future use - these become instance constants
80 mPrivilegeScope = scope;
81 mKeyHierarchy = keyHierarchy;
82 mPvcPolicy = pvcPolicy;
83 mCallerGuid = callerGuid;
84
85 // we are ready now
86 initCount = 1;
87 secdebug("cssm", "CSSM initialized");
88 }
89
90
91 //
92 // CSSM Termination processing.
93 // Returns true if this was the final (true) termination, false if a nested Init was undone.
94 //
95 bool CssmManager::terminate()
96 {
97 StLock<Mutex> _(mLock);
98 switch (initCount) {
99 case 0:
100 CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED);
101 case 1:
102 secdebug("cssm", "Terminating CSSM");
103 if (!moduleMap.empty())
104 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @#can't terminate with modules loaded
105 initCount = 0; // mark uninitialized
106 return true;
107 default:
108 initCount--; // nested INIT, just count down
109 secdebug("cssm", "CSSM nested termination (%d remaining)", initCount);
110 return false;
111 }
112 }
113
114
115 #if defined(RESTRICTED_CSP_LOADING)
116 static const char * const allowedCSPs[] = {
117 "/System/Library/Security/AppleCSP.bundle",
118 "/System/Library/Security/AppleCSPDL.bundle",
119 NULL
120 };
121 #endif
122
123
124 //
125 // Load a module (well, try).
126 //
127 void CssmManager::loadModule(const Guid &guid,
128 CSSM_KEY_HIERARCHY,
129 const ModuleCallback &callback)
130 {
131 StLock<Mutex> _(mLock);
132 ModuleMap::iterator it = moduleMap.find(guid);
133 Module *module;
134 if (it == moduleMap.end()) {
135 MdsComponent info(guid);
136 #if defined(RESTRICTED_CSP_LOADING)
137 // An abominable temporary hack for legal reasons. They made me do it!
138 if (info.supportsService(CSSM_SERVICE_CSP)) {
139 string loadPath = info.path();
140 for (const char * const *pp = allowedCSPs; *pp; pp++)
141 if (loadPath == *pp)
142 goto allowed;
143 CssmError::throwMe(CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED);
144 allowed: ;
145 }
146 #endif
147 secdebug("cssm", "loading module %s(%s) from %s",
148 info.name().c_str(), info.description().c_str(), info.path().c_str());
149 module = new Module(this, info, loader(info.path()));
150 moduleMap[guid] = module;
151 } else {
152 module = it->second;
153 secdebug("cssm", "%p reloaded module %s(%s) at %s",
154 module, module->name().c_str(), module->description().c_str(),
155 module->path().c_str());
156 }
157
158 // We are not playing the "key hierarchy" game around here.
159 // if we did, this is where we'd check the manifest.
160
161 module->add(callback);
162 }
163
164
165 //
166 // Unload a module.
167 // THREADS: Locking Manager(1), Module(2).
168 //
169 void CssmManager::unloadModule(const Guid &guid,
170 const ModuleCallback &callback)
171 {
172 StLock<Mutex> _(mLock);
173 Module *module = getModule(guid);
174 if (module->unload(callback)) {
175 secdebug("cssm", "%p module %s(%s) final unload",
176 module, module->name().c_str(), module->description().c_str());
177 moduleMap.erase(guid);
178 delete module;
179 } else
180 secdebug("cssm", "%p module %s(%s) load count now %u", module,
181 module->name().c_str(), module->description().c_str(), module->callbackCount());
182 }
183
184
185 //
186 // Introductions
187 //
188 void CssmManager::introduce(const Guid &,
189 CSSM_KEY_HIERARCHY)
190 {
191 StLock<Mutex> _(mLock);
192 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
193 }
194
195 void CssmManager::unIntroduce(const Guid &)
196 {
197 StLock<Mutex> _(mLock);
198 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
199 }
200
201
202 //
203 // Support.
204 // THREADS: These utilities run under lock protection by the caller.
205 //
206 void CssmManager::checkVersion(const CSSM_VERSION &version)
207 {
208 if (version.Major != 2)
209 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
210 if (version.Minor != 0)
211 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION);
212 }
213
214 Module *CssmManager::getModule(const Guid &guid)
215 {
216 ModuleMap::iterator it = moduleMap.find(guid);
217 if (it == moduleMap.end())
218 CssmError::throwMe(CSSMERR_CSSM_MODULE_NOT_LOADED);
219 return it->second;
220 }