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// 37CssmManager::CssmManager() 38{ 39 initCount = 0; // not yet initialized 40} 41 42CssmManager::~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// 53void 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// 95bool 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) 116static 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// 127void 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// 169void 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// 188void CssmManager::introduce(const Guid &, 189 CSSM_KEY_HIERARCHY) 190{ 191 StLock<Mutex> _(mLock); 192 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); 193} 194 195void 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// 206void 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 214Module *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} 221