/ OSX / libsecurity_cssm / lib / module.cpp
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  }