2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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 // manager - CSSM manager/supervisor objects.
30 #include <security_utilities/debugging.h>
34 // Constructing a CssmManager instance.
35 // This does almost nothing - the actual intialization happens in the initialize() method.
37 CssmManager::CssmManager()
39 initCount
= 0; // not yet initialized
42 CssmManager::~CssmManager()
45 secdebug("cssm", "CSSM forcibly shutting down");
50 // CSSM initialization.
51 // THREADS: This function must run in an uncontested environment.
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
)
59 StLock
<Mutex
> _(mLock
);
61 // check version first
62 checkVersion(version
);
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
);
71 secdebug("cssm", "re-initializing CSSM (%d levels)", initCount
);
75 // we don't support thread scope privileges
76 if (scope
== CSSM_PRIVILEGE_SCOPE_THREAD
)
77 CssmError::throwMe(CSSMERR_CSSM_SCOPE_NOT_SUPPORTED
);
79 // keep the init arguments for future use - these become instance constants
80 mPrivilegeScope
= scope
;
81 mKeyHierarchy
= keyHierarchy
;
82 mPvcPolicy
= pvcPolicy
;
83 mCallerGuid
= callerGuid
;
87 secdebug("cssm", "CSSM initialized");
92 // CSSM Termination processing.
93 // Returns true if this was the final (true) termination, false if a nested Init was undone.
95 bool CssmManager::terminate()
97 StLock
<Mutex
> _(mLock
);
100 CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED
);
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
108 initCount
--; // nested INIT, just count down
109 secdebug("cssm", "CSSM nested termination (%d remaining)", initCount
);
115 #if defined(RESTRICTED_CSP_LOADING)
116 static const char * const allowedCSPs
[] = {
117 "/System/Library/Security/AppleCSP.bundle",
118 "/System/Library/Security/AppleCSPDL.bundle",
125 // Load a module (well, try).
127 void CssmManager::loadModule(const Guid
&guid
,
129 const ModuleCallback
&callback
)
131 StLock
<Mutex
> _(mLock
);
132 ModuleMap::iterator it
= moduleMap
.find(guid
);
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
++)
143 CssmError::throwMe(CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED
);
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;
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());
158 // We are not playing the "key hierarchy" game around here.
159 // if we did, this is where we'd check the manifest.
161 module->add(callback
);
167 // THREADS: Locking Manager(1), Module(2).
169 void CssmManager::unloadModule(const Guid
&guid
,
170 const ModuleCallback
&callback
)
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
);
180 secdebug("cssm", "%p module %s(%s) load count now %u", module,
181 module->name().c_str(), module->description().c_str(), module->callbackCount());
188 void CssmManager::introduce(const Guid
&,
191 StLock
<Mutex
> _(mLock
);
192 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
195 void CssmManager::unIntroduce(const Guid
&)
197 StLock
<Mutex
> _(mLock
);
198 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
204 // THREADS: These utilities run under lock protection by the caller.
206 void CssmManager::checkVersion(const CSSM_VERSION
&version
)
208 if (version
.Major
!= 2)
209 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION
);
210 if (version
.Minor
!= 0)
211 CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION
);
214 Module
*CssmManager::getModule(const Guid
&guid
)
216 ModuleMap::iterator it
= moduleMap
.find(guid
);
217 if (it
== moduleMap
.end())
218 CssmError::throwMe(CSSMERR_CSSM_MODULE_NOT_LOADED
);