module.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 // 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 // 37 Module::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 // 56 Module::~Module() 57 { 58 } 59 60 61 bool 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 // 89 CSSM_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 // 130 void 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 // 140 void 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 152 CSSM_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_NO_METRICS 159 static_cast<Module *>(Context)->spiEvent(EventType, 160 Guid::required(ModuleGuid), 161 SubserviceId, 162 ServiceType); 163 END_API(CSSM) 164 }