2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // cssmplugin - adapter framework for C++-based CDSA plugin modules
22 // A note on locking: Attachments are effectively reference counted in CSSM.
23 // CSSM will not let a client detach an attachment that has a(nother) thread
24 // active in its code. Thus, our locks merely protect global maps; they do not
25 // need (or try) to close the classic use-and-delete window.
27 #include <security_cdsa_plugin/cssmplugin.h>
28 #include <security_cdsa_plugin/pluginsession.h>
32 ModuleNexus
<CssmPlugin::SessionMap
> CssmPlugin::sessionMap
;
35 CssmPlugin::CssmPlugin()
40 CssmPlugin::~CssmPlugin()
42 // Note: if mLoaded, we're being unloaded forcibly.
43 // (CSSM wouldn't do this to us in normal operation.)
49 // CSSM only calls this once for a module, and multiplexes any additional
50 // CSSM_ModuleLoad calls internally. So this is only called when we have just
51 // been loaded (and not yet attached).
53 void CssmPlugin::moduleLoad(const Guid
&cssmGuid
,
54 const Guid
&moduleGuid
,
55 const ModuleCallback
&newCallback
)
58 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
62 // let the implementation know that we're loading
66 mCallback
= newCallback
;
73 // The callback passed here will be the same passed to load.
74 // CSSM only calls this on a "final" CSSM_ModuleUnload, after all attachments
75 // are destroyed and (just) before we are physically unloaded.
77 void CssmPlugin::moduleUnload(const Guid
&cssmGuid
,
78 const Guid
&moduleGuid
,
79 const ModuleCallback
&oldCallback
)
81 // check the callback vector
82 if (!mLoaded
|| oldCallback
!= mCallback
)
83 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
85 // tell our subclass that we're closing down
94 // Create one attachment session. This is what CSSM calls to process
95 // a CSSM_ModuleAttach call. moduleLoad() has already been called and has
96 // returned successfully.
98 void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle
,
99 const Guid
&newCssmGuid
,
100 const Guid
&moduleGuid
,
101 const Guid
&moduleManagerGuid
,
102 const Guid
&callerGuid
,
103 const CSSM_VERSION
&version
,
105 CSSM_SERVICE_TYPE subserviceType
,
106 CSSM_ATTACH_FLAGS attachFlags
,
107 CSSM_KEY_HIERARCHY keyHierarchy
,
108 const CSSM_UPCALLS
&upcalls
,
109 CSSM_MODULE_FUNCS_PTR
&funcTbl
)
111 // basic (in)sanity checks
112 if (moduleGuid
!= mMyGuid
)
113 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID
);
115 // make the new session object, hanging in thin air
116 auto_ptr
<PluginSession
> session(this->makeSession(theHandle
,
118 subserviceId
, subserviceType
,
122 // haggle with the implementor
123 funcTbl
= session
->construct();
125 // commit this session creation
126 StLock
<Mutex
> _(sessionMap());
127 sessionMap()[theHandle
] = session
.release();
132 // Undo a (single) module attachment. This calls the detach() method on
133 // the Session object representing the attachment. This is only called
134 // if session->construct() has succeeded previously.
135 // If session->detach() fails, we do not destroy the session and it continues
136 // to live, though its handle may have (briefly) been invalid. This is for
137 // desperate "mustn't go right now" situations and should not be abused.
138 // CSSM always has the ability to ditch you without your consent if you are
141 void CssmPlugin::moduleDetach(CSSM_MODULE_HANDLE handle
)
143 // locate the plugin and hold the sessionMapLock
144 PluginSession
*session
;
146 StLock
<Mutex
> _(sessionMap());
147 SessionMap::iterator it
= sessionMap().find(handle
);
148 if (it
== sessionMap().end())
149 CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE
);
150 session
= it
->second
;
151 sessionMap().erase(it
);
154 // let the session know it is going away
159 // session detach failed - put the plugin back and fail
160 StLock
<Mutex
> _(sessionMap());
161 sessionMap()[handle
] = session
;
168 // Send an official CSSM module callback message upstream
170 void CssmPlugin::sendCallback(CSSM_MODULE_EVENT event
, uint32 ssid
,
171 CSSM_SERVICE_TYPE serviceType
) const
174 mCallback(event
, mMyGuid
, ssid
, serviceType
);
179 // Default subclass hooks.
180 // The default implementations succeed without doing anything.
182 void CssmPlugin::load() { }
184 void CssmPlugin::unload() { }