2346e8fad821b38b124b32c25be6dd6499ed6be3
[shibboleth/sp.git] / shib-target / shib-target.h
1 /*
2  *  Copyright 2001-2005 Internet2
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * shib-target.h -- top-level header file for the SHIB Common Target Library
19  *
20  * Created by:  Derek Atkins <derek@ihtfp.com>
21  *
22  * $Id$
23  */
24
25 #ifndef SHIB_TARGET_H
26 #define SHIB_TARGET_H
27
28 // New headers
29 #include <shibsp/AbstractSPRequest.h>
30 #include <shibsp/Application.h>
31 #include <shibsp/ServiceProvider.h>
32 #include <shibsp/remoting/ListenerService.h>
33
34 // Old headers
35 #include <saml/saml.h>
36 #include <shib/shib.h>
37
38 #ifdef WIN32
39 # ifndef SHIBTARGET_EXPORTS
40 #  define SHIBTARGET_EXPORTS __declspec(dllimport)
41 # endif
42 # define SHIB_SCHEMAS "/opt/shibboleth-sp/share/xml/shibboleth"
43 # define SHIB_CONFIG "/opt/shibboleth-sp/etc/shibboleth/shibboleth.xml"
44 #else
45 # include <shib-target/shib-paths.h>
46 # define SHIBTARGET_EXPORTS
47 #endif
48
49 namespace shibtarget {
50   
51     // Abstract APIs for access to configuration information
52     
53     // Forward declaration
54     class SHIBTARGET_EXPORTS ShibTarget;
55
56     /**
57      * Interface to a protocol handler
58      * 
59      * Protocol handlers perform system functions such as processing SAML protocol
60      * messages to create and logout sessions or creating protocol requests.
61      */
62     struct SHIBTARGET_EXPORTS IHandler : public virtual saml::IPlugIn
63     {
64         IHandler() : m_props(NULL) {}
65         virtual ~IHandler() {}
66         virtual const shibsp::PropertySet* getProperties() const { return m_props; }
67         virtual void setProperties(const shibsp::PropertySet* properties) { m_props=properties; }
68         virtual std::pair<bool,long> run(ShibTarget* st, bool isHandler=true) const=0;
69     private:
70         const shibsp::PropertySet* m_props;
71     };
72     
73     /**
74      * Interface to Shibboleth Applications, which exposes most of the functionality
75      * required to process web requests or security protocol messages for resources
76      * associated with them.
77      * 
78      * Applications are implementation-specific, but generally correspond to collections
79      * of resources related to one another in logical ways, such as a virtual host or
80      * a Java servlet context. Most complex configuration data is associated with an
81      * Application. Implementations should always expose an application named "default"
82      * as a last resort.
83      */
84     struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::Application,
85         public virtual shibboleth::ShibBrowserProfile::ITokenValidator
86     {
87         virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
88         virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
89         virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
90
91         // caller is borrowing object, must use within scope of config lock
92         virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0;
93         virtual const saml::SAMLBinding* getBinding(const XMLCh* binding) const=0;
94
95         // caller is given ownership of object, must use and delete within scope of config lock
96         virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0;
97
98         // general token validation based on conditions, signatures, etc.
99         virtual void validateToken(
100             saml::SAMLAssertion* token,
101             time_t t=0,
102             const opensaml::saml2md::RoleDescriptor* role=NULL,
103             const xmltooling::TrustEngine* trust=NULL
104             ) const=0;
105
106         // Used to locate a default or designated session initiator for automatic sessions
107         virtual const IHandler* getDefaultSessionInitiator() const=0;
108         virtual const IHandler* getSessionInitiatorById(const char* id) const=0;
109         
110         // Used by session initiators to get endpoint to forward to IdP/WAYF
111         virtual const IHandler* getDefaultAssertionConsumerService() const=0;
112         virtual const IHandler* getAssertionConsumerServiceByIndex(unsigned short index) const=0;
113         virtual saml::Iterator<const IHandler*> getAssertionConsumerServicesByBinding(const XMLCh* binding) const=0;
114         
115         // Used by dispatcher to locate the handler for a request
116         virtual const IHandler* getHandler(const char* path) const=0;
117
118         virtual ~IApplication() {}
119     };
120
121     /**
122      * OpenSAML binding hook
123      *
124      * Instead of wrapping the binding to deal with mutual authentication, we
125      * just use the HTTP hook functionality offered by OpenSAML. The hook will
126      * register "itself" as a globalCtx pointer with the SAML binding and the caller
127      * will declare and pass the embedded struct as callCtx for use by the hook.
128      */
129     class ShibHTTPHook : virtual public saml::SAMLSOAPHTTPBinding::HTTPHook
130     {
131     public:
132         ShibHTTPHook(const xmltooling::TrustEngine* trust) : m_trust(trust) {}
133         virtual ~ShibHTTPHook() {}
134         
135         // Only hook we need here is for outgoing connection to server.
136         virtual bool outgoing(saml::HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL);
137
138         // Client declares a context object and pass as callCtx to send() method.
139         class ShibHTTPHookCallContext {
140         public:
141             ShibHTTPHookCallContext(const shibsp::PropertySet* credUse, const opensaml::saml2md::RoleDescriptor* role)
142                 : m_credUse(credUse), m_role(role), m_hook(NULL), m_authenticated(false) {}
143             const ShibHTTPHook* getHook() {return m_hook;}
144             const shibsp::PropertySet* getCredentialUse() {return m_credUse;}
145             const opensaml::saml2md::RoleDescriptor* getRoleDescriptor() {return m_role;}
146             bool isAuthenticated() const {return m_authenticated;}
147             void setAuthenticated() {m_authenticated=true;}
148             
149         private:
150             const shibsp::PropertySet* m_credUse;
151             const opensaml::saml2md::RoleDescriptor* m_role;
152             ShibHTTPHook* m_hook;
153             bool m_authenticated;
154             friend class ShibHTTPHook;
155         };
156         
157         const xmltooling::TrustEngine* getTrustEngine() const {return m_trust;}
158     private:
159         const xmltooling::TrustEngine* m_trust;
160     };
161
162     /**
163      * Interface to a cached user session.
164      * 
165      * Cache entries provide implementations with access to the raw SAML information they
166      * need to publish or provide access to the data for applications to use. All creation
167      * or access to entries is through the ISessionCache interface, and callers must unlock
168      * the entry when finished using it, rather than explicitly freeing them.
169      */
170     struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
171     {
172         virtual const char* getClientAddress() const=0;
173         virtual const char* getProviderId() const=0;
174         virtual std::pair<const char*,const saml::SAMLSubject*> getSubject(bool xml=true, bool obj=false) const=0;
175         virtual const char* getAuthnContext() const=0;
176         virtual std::pair<const char*,const saml::SAMLResponse*> getTokens(bool xml=true, bool obj=false) const=0;
177         virtual std::pair<const char*,const saml::SAMLResponse*> getFilteredTokens(bool xml=true, bool obj=false) const=0;
178         virtual ~ISessionCacheEntry() {}
179     };
180
181     /**
182      * Interface to a sink for session cache events.
183      *
184      * All caches support registration of a backing store that can be informed
185      * of significant events in the lifecycle of a cache entry.
186      */
187     struct SHIBTARGET_EXPORTS ISessionCacheStore
188     {
189         virtual HRESULT onCreate(
190             const char* key,
191             const IApplication* application,
192             const ISessionCacheEntry* entry,
193             int majorVersion,
194             int minorVersion,
195             time_t created
196             )=0;
197         virtual HRESULT onRead(
198             const char* key,
199             std::string& applicationId,
200             std::string& clientAddress,
201             std::string& providerId,
202             std::string& subject,
203             std::string& authnContext,
204             std::string& tokens,
205             int& majorVersion,
206             int& minorVersion,
207             time_t& created,
208             time_t& accessed
209             )=0;
210         virtual HRESULT onRead(const char* key, time_t& accessed)=0;
211         virtual HRESULT onRead(const char* key, std::string& tokens)=0;
212         virtual HRESULT onUpdate(const char* key, const char* tokens=NULL, time_t lastAccess=0)=0;
213         virtual HRESULT onDelete(const char* key)=0;
214         virtual ~ISessionCacheStore() {}
215     };
216
217     /**
218      * Interface to the session cache.
219      * 
220      * The session cache abstracts a persistent (meaning across requests) cache of
221      * instances of the ISessionCacheEntry interface. Creation of new entries and entry
222      * lookup are confined to this interface to enable implementations to flexibly
223      * remote and/or optimize calls by implementing custom versions of the
224      * ISessionCacheEntry interface as required.
225      */
226     struct SHIBTARGET_EXPORTS ISessionCache : public virtual saml::IPlugIn
227     {
228         virtual std::string insert(
229             const IApplication* application,
230             const opensaml::saml2md::RoleDescriptor* source,
231             const char* client_addr,
232             const saml::SAMLSubject* subject,
233             const char* authnContext,
234             const saml::SAMLResponse* tokens
235             )=0;
236         virtual ISessionCacheEntry* find(
237             const char* key, const IApplication* application, const char* client_addr
238             )=0;
239         virtual void remove(
240             const char* key, const IApplication* application, const char* client_addr
241             )=0;
242
243         virtual bool setBackingStore(ISessionCacheStore* store)=0;
244         virtual ~ISessionCache() {}
245     };
246
247     #define MEMORY_SESSIONCACHE "edu.internet2.middleware.shibboleth.sp.provider.MemorySessionCacheProvider"
248     #define MYSQL_SESSIONCACHE  "edu.internet2.middleware.shibboleth.sp.provider.MySQLSessionCacheProvider"
249     #define ODBC_SESSIONCACHE   "edu.internet2.middleware.shibboleth.sp.provider.ODBCSessionCacheProvider"
250
251     #define MYSQL_REPLAYCACHE   "edu.internet2.middleware.shibboleth.sp.provider.MySQLReplayCacheProvider"
252     #define ODBC_REPLAYCACHE    "edu.internet2.middleware.shibboleth.sp.provider.ODBCReplayCacheProvider"
253
254
255     struct SHIBTARGET_EXPORTS IConfig : public virtual shibsp::ServiceProvider
256     {
257         virtual ISessionCache* getSessionCache() const=0;
258         virtual saml::IReplayCache* getReplayCache() const=0;
259         virtual ~IConfig() {}
260     };
261
262     class SHIBTARGET_EXPORTS ShibTargetConfig
263     {
264     public:
265         ShibTargetConfig() : m_ini(NULL) {}
266         virtual ~ShibTargetConfig() {}
267         
268         virtual bool init(const char* schemadir) = 0;
269         virtual bool load(const char* config) = 0;
270         virtual void shutdown() = 0;
271
272         virtual IConfig* getINI() const {return m_ini;}
273
274         static ShibTargetConfig& getConfig();
275
276     protected:
277         IConfig* m_ini;
278     };
279
280     class ShibTargetPriv;
281     class SHIBTARGET_EXPORTS ShibTarget : public shibsp::AbstractSPRequest {
282     public:
283         ShibTarget(const IApplication* app);
284         virtual ~ShibTarget(void);
285
286         // These next two APIs are used to obtain the module-specific "OK"
287         // and "Decline" results.  OK means "we believe that this request
288         // should be accepted".  Declined means "we believe that this is
289         // not a shibbolized request so we have no comment".
290
291         virtual long returnDecline();
292         virtual long returnOK();
293
294         //
295         // Note:  Subclasses need not implement anything below this line
296         //
297
298         // These functions implement the server-agnostic shibboleth engine
299         // The web server modules implement a subclass and then call into 
300         // these methods once they instantiate their request object.
301         // 
302         // Return value:
303         //   these APIs will always return the result of sendPage(), sendRedirect(),
304         //   returnDecline(), or returnOK() in the void* portion of the return code.
305         //   Exactly what those values are is module- (subclass-) implementation
306         //   specific.  The 'bool' part of the return value declares whether the
307         //   void* is valid or not.  If the bool is true then the void* is valid.
308         //   If the bool is false then the API did not call any callback, the void*
309         //   is not valid, and the caller should continue processing (the API Call
310         //   finished successfully).
311         //
312         //   The handleProfile argument declares whether doCheckAuthN() should
313         //   automatically call doHandlePOST() when it encounters a request for
314         //   the ShireURL;  if false it will call returnOK() instead.
315         //
316         std::pair<bool,long> doCheckAuthN(bool handler = false);
317         std::pair<bool,long> doHandler();
318         std::pair<bool,long> doCheckAuthZ();
319         std::pair<bool,long> doExportAssertions(bool requireSession = true);
320
321         // Basic request access in case any plugins need the info
322         virtual const IConfig* getConfig() const;
323         virtual const IApplication* getApplication() const;
324         
325     protected:
326         ShibTarget();
327
328         // Internal APIs
329
330         // Initialize the request from the parsed URL
331         // scheme == http, https, etc
332         // hostname == server name
333         // port == server port
334         // uri == resource path
335         // method == GET, POST, etc.
336         void init(
337             const char* scheme,
338             const char* hostname,
339             int port,
340             const char* uri
341             );
342
343     private:
344         mutable ShibTargetPriv* m_priv;
345         friend class ShibTargetPriv;
346     };
347
348 }
349
350 #endif /* SHIB_TARGET_H */