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// module - CSSM Module objects 27// 28#include "module.h" 29#include "manager.h" 30#include "attachment.h" 31#include <security_cdsa_utilities/cssmbridge.h> 32 33 34// 35// Module object construction. 36// 37Module::Module(CssmManager *mgr, const MdsComponent &info, Plugin *plug) 38: MdsComponent(info), cssm(*mgr), plugin(plug) 39{ 40 // invoke module's load entry (tell it it's being loaded) 41 if (CSSM_RETURN err = plugin->load(&gGuidCssm, // CSSM's Guid 42 &myGuid(), // module's Guid 43 spiEventRelay, this)) { 44 plugin->unload(); 45 CssmError::throwMe(err); // self-destruct this module 46 } 47} 48 49 50// 51// Destroy the module object. 52// The unload() method must have succeeded and returned true before 53// you get to delete a Module. A destructor is too precarious a place 54// to negotiate with a plugin... 55// 56Module::~Module() 57{ 58} 59 60 61bool Module::unload(const ModuleCallback &callback) 62{ 63 StLock<Mutex> _(mLock); 64 // locked module - no more attachment creations possible 65 if (callbackCount() == 1) { 66 // would be last callback if successful, check for actual unload 67 if (attachmentCount() > 0) 68 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @# module is busy 69 // no attachments active - we are idle and ready to unload 70 if (CSSM_RETURN err = plugin->unload(&gGuidCssm, // CSSM's Guid 71 &myGuid(), // module's Guid 72 spiEventRelay, this)) // our callback 73 CssmError::throwMe(err); // tough... 74 // okay, commit 75 remove(callback); 76 plugin->unload(); 77 return true; 78 } else { 79 // more callbacks - we're not going to unload 80 remove(callback); 81 return false; 82 } 83} 84 85 86// 87// Create a new attachment for this module 88// 89CSSM_HANDLE Module::attach(const CSSM_VERSION &version, 90 uint32 subserviceId, 91 CSSM_SERVICE_TYPE subserviceType, 92 const CSSM_API_MEMORY_FUNCS &memoryOps, 93 CSSM_ATTACH_FLAGS attachFlags, 94 CSSM_KEY_HIERARCHY keyHierarchy, 95 CSSM_FUNC_NAME_ADDR *functionTable, 96 uint32 functionTableSize) 97{ 98 StLock<Mutex> _(mLock); 99 100 // check if the module can do this kind of service 101 if (!supportsService(subserviceType)) 102 CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK); 103 104 Attachment *attachment = cssm.attachmentMakerFor(subserviceType)->make(this, 105 version, 106 subserviceId, subserviceType, 107 memoryOps, 108 attachFlags, 109 keyHierarchy, 110 functionTable, functionTableSize); 111 112 try { 113 // add to module's attachment map 114 attachmentMap.insert(AttachmentMap::value_type(attachment->handle(), attachment)); 115 } catch (...) { 116 delete attachment; 117 throw; 118 } 119 120 // all done 121 return attachment->handle(); 122} 123 124 125// 126// Detach an Attachment from this module. 127// THREADS: Requires the attachment to be idled out, i.e. caller 128// is responsible for keeping more users from entering it. 129// 130void Module::detach(Attachment *attachment) 131{ 132 StLock<Mutex> _(mLock); 133 attachmentMap.erase(attachment->handle()); 134} 135 136 137// 138// Handle events sent by the loaded module. 139// 140void Module::spiEvent(CSSM_MODULE_EVENT event, 141 const Guid &guid, 142 uint32 subserviceId, 143 CSSM_SERVICE_TYPE serviceType) 144{ 145 StLock<Mutex> _(mLock); 146 if (guid != myGuid()) 147 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); 148 callbackSet(event, guid, subserviceId, serviceType); 149} 150 151// static shim 152CSSM_RETURN Module::spiEventRelay(const CSSM_GUID *ModuleGuid, 153 void *Context, 154 uint32 SubserviceId, 155 CSSM_SERVICE_TYPE ServiceType, 156 CSSM_MODULE_EVENT EventType) 157{ 158 BEGIN_API 159 static_cast<Module *>(Context)->spiEvent(EventType, 160 Guid::required(ModuleGuid), 161 SubserviceId, 162 ServiceType); 163 END_API(CSSM) 164} 165