manager.cpp
1 /* 2 * Copyright (c) 2000-2001,2003-2004,2011,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 // 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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 secinfo("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 }