/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ // // manager - CSSM manager/supervisor objects. // #ifdef __MWERKS__ #define _CPP_MANAGER #endif #include "manager.h" #include "module.h" #include //#include // // Constructing a CssmManager instance. // This does almost nothing - the actual intialization happens in the initialize() method. // CssmManager::CssmManager() : MdsComponent(gGuidCssm) { initCount = 0; // not yet initialized } CssmManager::~CssmManager() { if (initCount > 0) debug("cssm", "CSSM forcibly shutting down"); } // // CSSM initialization. // THREADS: This function must run in an uncontested environment. // void CssmManager::initialize (const CSSM_VERSION &version, CSSM_PRIVILEGE_SCOPE scope, const Guid &callerGuid, CSSM_KEY_HIERARCHY keyHierarchy, CSSM_PVC_MODE &pvcPolicy) { StLock _(mLock); // check version first checkVersion(version); if (initCount) { // re-initialization processing as per CSSM spec if (pvcPolicy != mPvcPolicy) { pvcPolicy = mPvcPolicy; // return old value CssmError::throwMe(CSSMERR_CSSM_PVC_ALREADY_CONFIGURED); } initCount++; debug("cssm", "re-initializing CSSM (%d levels)", initCount); return; } // we don't support thread scope privileges if (scope == CSSM_PRIVILEGE_SCOPE_THREAD) CssmError::throwMe(CSSMERR_CSSM_SCOPE_NOT_SUPPORTED); // keep the init arguments for future use - these become instance constants mPrivilegeScope = scope; mKeyHierarchy = keyHierarchy; mPvcPolicy = pvcPolicy; mCallerGuid = callerGuid; // we are ready now initCount = 1; debug("cssm", "CSSM initialized"); } // // CSSM Termination processing. // Returns true if this was the final (true) termination, false if a nested Init was undone. // bool CssmManager::terminate() { StLock _(mLock); switch (initCount) { case 0: CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED); case 1: debug("cssm", "Terminating CSSM"); if (!moduleMap.empty()) CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @#can't terminate with modules loaded initCount = 0; // mark uninitialized return true; default: initCount--; // nested INIT, just count down debug("cssm", "CSSM nested termination (%d remaining)", initCount); return false; } } #if defined(RESTRICTED_CSP_LOADING) static char *allowedCSPs[] = { "/System/Library/Security/AppleCSP.bundle", "/System/Library/Security/AppleCSPDL.bundle", NULL }; #endif // // Load a module (well, try). // void CssmManager::loadModule(const Guid &guid, CSSM_KEY_HIERARCHY, const ModuleCallback &callback) { StLock _(mLock); ModuleMap::iterator it = moduleMap.find(guid); Module *module; if (it == moduleMap.end()) { MdsComponent info(guid); #if defined(RESTRICTED_CSP_LOADING) // An abominable temporary hack for legal reasons. They made me do it! if (info.supportsService(CSSM_SERVICE_CSP)) { string loadPath = info.path(); for (char **pp = allowedCSPs; *pp; pp++) if (loadPath == *pp) goto allowed; CssmError::throwMe(CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED); allowed: ; } #endif module = new Module(this, info, loader(info.path())); moduleMap[guid] = module; } else { module = it->second; } module->add(callback); //@@@ verify against keyHierarchy } // // Unload a module. // THREADS: Locking Manager(1), Module(2). // void CssmManager::unloadModule(const Guid &guid, const ModuleCallback &callback) { StLock _(mLock); Module *module = getModule(guid); if (module->unload(callback)) { moduleMap.erase(guid); delete module; } } // // Introductions // void CssmManager::introduce(const Guid &, CSSM_KEY_HIERARCHY) { StLock _(mLock); CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } void CssmManager::unIntroduce(const Guid &) { StLock _(mLock); CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } // // Support. // THREADS: These utilities run under lock protection by the caller. // void CssmManager::checkVersion(const CSSM_VERSION &version) { if (version.Major != 2) CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); if (version.Minor != 0) CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); } Module *CssmManager::getModule(const Guid &guid) { ModuleMap::iterator it = moduleMap.find(guid); if (it == moduleMap.end()) CssmError::throwMe(CSSMERR_CSSM_MODULE_NOT_LOADED); return it->second; }