Move Shib constants to new lib, fixed symbol conflicts.
[shibboleth/cpp-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 <saml/base.h>
30 #include <saml/saml2/metadata/MetadataProvider.h>
31 #include <shibsp/ListenerService.h>
32 #include <shibsp/PropertySet.h>
33 #include <xmltooling/security/TrustEngine.h>
34
35 // Old headers
36 #include <saml/saml.h>
37 #include <shib/shib.h>
38
39 #ifdef WIN32
40 # ifndef SHIBTARGET_EXPORTS
41 #  define SHIBTARGET_EXPORTS __declspec(dllimport)
42 # endif
43 # define SHIB_SCHEMAS "/opt/shibboleth-sp/share/xml/shibboleth"
44 # define SHIB_CONFIG "/opt/shibboleth-sp/etc/shibboleth/shibboleth.xml"
45 #else
46 # include <shib-target/shib-paths.h>
47 # define SHIBTARGET_EXPORTS
48 #endif
49
50 namespace shibtarget {
51   
52     DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ListenerException,SAMLException);
53     DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ConfigurationException,SAMLException);
54
55     // Abstract APIs for access to configuration information
56     
57     // Forward declaration
58     class SHIBTARGET_EXPORTS ShibTarget;
59
60     /**
61      * Interface to a protocol handler
62      * 
63      * Protocol handlers perform system functions such as processing SAML protocol
64      * messages to create and logout sessions or creating protocol requests.
65      */
66     struct SHIBTARGET_EXPORTS IHandler : public virtual saml::IPlugIn
67     {
68         IHandler() : m_props(NULL) {}
69         virtual ~IHandler() {}
70         virtual const shibsp::PropertySet* getProperties() const { return m_props; }
71         virtual void setProperties(const shibsp::PropertySet* properties) { m_props=properties; }
72         virtual std::pair<bool,void*> run(ShibTarget* st, bool isHandler=true) const=0;
73     private:
74         const shibsp::PropertySet* m_props;
75     };
76     
77     /**
78      * Interface to Shibboleth Applications, which exposes most of the functionality
79      * required to process web requests or security protocol messages for resources
80      * associated with them.
81      * 
82      * Applications are implementation-specific, but generally correspond to collections
83      * of resources related to one another in logical ways, such as a virtual host or
84      * a Java servlet context. Most complex configuration data is associated with an
85      * Application. Implementations should always expose an application named "default"
86      * as a last resort.
87      */
88     struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::PropertySet,
89         public virtual shibboleth::ShibBrowserProfile::ITokenValidator
90     {
91         virtual const char* getId() const=0;
92         virtual const char* getHash() const=0;
93         
94         virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
95         virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
96         virtual saml::Iterator<shibboleth::IMetadata*> getMetadataProviders() const=0;
97         virtual saml::Iterator<shibboleth::ITrust*> getTrustProviders() const=0;
98         virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
99         virtual const shibsp::PropertySet* getCredentialUse(const shibboleth::IEntityDescriptor* provider) const=0;
100
101         virtual const opensaml::saml2md::MetadataProvider* getMetadataProvider() const=0;
102         virtual const xmltooling::TrustEngine* getTrustEngine() const=0;
103
104         // caller is borrowing object, must use within scope of config lock
105         virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0;
106         virtual const saml::SAMLBinding* getBinding(const XMLCh* binding) const=0;
107
108         // caller is given ownership of object, must use and delete within scope of config lock
109         virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0;
110
111         // general token validation based on conditions, signatures, etc.
112         virtual void validateToken(
113             saml::SAMLAssertion* token,
114             time_t t=0,
115             const shibboleth::IRoleDescriptor* role=NULL,
116             const saml::Iterator<shibboleth::ITrust*>& trusts=EMPTY(shibboleth::ITrust*)
117             ) const=0;
118
119         // Used to locate a default or designated session initiator for automatic sessions
120         virtual const IHandler* getDefaultSessionInitiator() const=0;
121         virtual const IHandler* getSessionInitiatorById(const char* id) const=0;
122         
123         // Used by session initiators to get endpoint to forward to IdP/WAYF
124         virtual const IHandler* getDefaultAssertionConsumerService() const=0;
125         virtual const IHandler* getAssertionConsumerServiceByIndex(unsigned short index) const=0;
126         virtual saml::Iterator<const IHandler*> getAssertionConsumerServicesByBinding(const XMLCh* binding) const=0;
127         
128         // Used by dispatcher to locate the handler for a request
129         virtual const IHandler* getHandler(const char* path) const=0;
130
131         virtual ~IApplication() {}
132     };
133
134     /**
135      * OpenSAML binding hook
136      *
137      * Instead of wrapping the binding to deal with mutual authentication, we
138      * just use the HTTP hook functionality offered by OpenSAML. The hook will
139      * register "itself" as a globalCtx pointer with the SAML binding and the caller
140      * will declare and pass the embedded struct as callCtx for use by the hook.
141      */
142     class ShibHTTPHook : virtual public saml::SAMLSOAPHTTPBinding::HTTPHook
143     {
144     public:
145         ShibHTTPHook(const saml::Iterator<shibboleth::ITrust*>& trusts, const saml::Iterator<shibboleth::ICredentials*>& creds)
146             : m_trusts(trusts), m_creds(creds) {}
147         virtual ~ShibHTTPHook() {}
148         
149         // Only hook we need here is for outgoing connection to server.
150         virtual bool outgoing(saml::HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL);
151
152         // Client declares a context object and pass as callCtx to send() method.
153         class ShibHTTPHookCallContext {
154         public:
155             ShibHTTPHookCallContext(const shibsp::PropertySet* credUse, const shibboleth::IRoleDescriptor* role)
156                 : m_credUse(credUse), m_role(role), m_hook(NULL), m_authenticated(false) {}
157             const ShibHTTPHook* getHook() {return m_hook;}
158             const shibsp::PropertySet* getCredentialUse() {return m_credUse;}
159             const shibboleth::IRoleDescriptor* getRoleDescriptor() {return m_role;}
160             bool isAuthenticated() const {return m_authenticated;}
161             void setAuthenticated() {m_authenticated=true;}
162             
163         private:
164             const shibsp::PropertySet* m_credUse;
165             const shibboleth::IRoleDescriptor* m_role;
166             ShibHTTPHook* m_hook;
167             bool m_authenticated;
168             friend class ShibHTTPHook;
169         };
170         
171         const saml::Iterator<shibboleth::ITrust*>& getTrustProviders() const {return m_trusts;}
172         const saml::Iterator<shibboleth::ICredentials*>& getCredentialProviders() const {return m_creds;}
173     private:
174         saml::Iterator<shibboleth::ITrust*> m_trusts;
175         saml::Iterator<shibboleth::ICredentials*> m_creds;
176     };
177
178     /**
179      * Interface to a cached user session.
180      * 
181      * Cache entries provide implementations with access to the raw SAML information they
182      * need to publish or provide access to the data for applications to use. All creation
183      * or access to entries is through the ISessionCache interface, and callers must unlock
184      * the entry when finished using it, rather than explicitly freeing them.
185      */
186     struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
187     {
188         virtual const char* getClientAddress() const=0;
189         virtual const char* getProviderId() const=0;
190         virtual std::pair<const char*,const saml::SAMLSubject*> getSubject(bool xml=true, bool obj=false) const=0;
191         virtual const char* getAuthnContext() const=0;
192         virtual std::pair<const char*,const saml::SAMLResponse*> getTokens(bool xml=true, bool obj=false) const=0;
193         virtual std::pair<const char*,const saml::SAMLResponse*> getFilteredTokens(bool xml=true, bool obj=false) const=0;
194         virtual ~ISessionCacheEntry() {}
195     };
196
197     /**
198      * Interface to a sink for session cache events.
199      *
200      * All caches support registration of a backing store that can be informed
201      * of significant events in the lifecycle of a cache entry.
202      */
203     struct SHIBTARGET_EXPORTS ISessionCacheStore
204     {
205         virtual HRESULT onCreate(
206             const char* key,
207             const IApplication* application,
208             const ISessionCacheEntry* entry,
209             int majorVersion,
210             int minorVersion,
211             time_t created
212             )=0;
213         virtual HRESULT onRead(
214             const char* key,
215             std::string& applicationId,
216             std::string& clientAddress,
217             std::string& providerId,
218             std::string& subject,
219             std::string& authnContext,
220             std::string& tokens,
221             int& majorVersion,
222             int& minorVersion,
223             time_t& created,
224             time_t& accessed
225             )=0;
226         virtual HRESULT onRead(const char* key, time_t& accessed)=0;
227         virtual HRESULT onRead(const char* key, std::string& tokens)=0;
228         virtual HRESULT onUpdate(const char* key, const char* tokens=NULL, time_t lastAccess=0)=0;
229         virtual HRESULT onDelete(const char* key)=0;
230         virtual ~ISessionCacheStore() {}
231     };
232
233     /**
234      * Interface to the session cache.
235      * 
236      * The session cache abstracts a persistent (meaning across requests) cache of
237      * instances of the ISessionCacheEntry interface. Creation of new entries and entry
238      * lookup are confined to this interface to enable implementations to flexibly
239      * remote and/or optimize calls by implementing custom versions of the
240      * ISessionCacheEntry interface as required.
241      */
242     struct SHIBTARGET_EXPORTS ISessionCache : public virtual saml::IPlugIn
243     {
244         virtual std::string insert(
245             const IApplication* application,
246             const shibboleth::IEntityDescriptor* source,
247             const char* client_addr,
248             const saml::SAMLSubject* subject,
249             const char* authnContext,
250             const saml::SAMLResponse* tokens
251             )=0;
252         virtual ISessionCacheEntry* find(
253             const char* key, const IApplication* application, const char* client_addr
254             )=0;
255         virtual void remove(
256             const char* key, const IApplication* application, const char* client_addr
257             )=0;
258
259         virtual bool setBackingStore(ISessionCacheStore* store)=0;
260         virtual ~ISessionCache() {}
261     };
262
263     /**
264      * Interface to an access control plugin
265      * 
266      * Access control plugins return authorization decisions based on the intersection
267      * of the resource request and the active session. They can be implemented through
268      * cross-platform or platform-specific mechanisms.
269      */
270     struct SHIBTARGET_EXPORTS IAccessControl : public virtual saml::ILockable, public virtual saml::IPlugIn
271     {
272         virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const=0;
273         virtual ~IAccessControl() {}
274     };
275
276     /**
277      * Interface to a request mapping plugin
278      * 
279      * Request mapping plugins return configuration settings that apply to resource requests.
280      * They can be implemented through cross-platform or platform-specific mechanisms.
281      */
282     struct SHIBTARGET_EXPORTS IRequestMapper : public virtual saml::ILockable, public virtual saml::IPlugIn
283     {
284         typedef std::pair<const shibsp::PropertySet*,IAccessControl*> Settings;
285         virtual Settings getSettings(ShibTarget* st) const=0;
286         virtual ~IRequestMapper() {}
287     };
288     
289     struct SHIBTARGET_EXPORTS IConfig : public virtual saml::ILockable, public virtual shibsp::PropertySet, public virtual saml::IPlugIn
290     {
291         // loads initial configuration
292         virtual void init()=0;
293
294         virtual shibsp::ListenerService* getListener() const=0;
295         virtual ISessionCache* getSessionCache() const=0;
296         virtual saml::IReplayCache* getReplayCache() const=0;
297         virtual IRequestMapper* getRequestMapper() const=0;
298         virtual const IApplication* getApplication(const char* applicationId) const=0;
299         virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
300         virtual ~IConfig() {}
301     };
302
303     class SHIBTARGET_EXPORTS ShibTargetConfig
304     {
305     public:
306         ShibTargetConfig() : m_ini(NULL) {}
307         virtual ~ShibTargetConfig() {}
308         
309         virtual bool init(const char* schemadir) = 0;
310         virtual bool load(const char* config) = 0;
311         virtual void shutdown() = 0;
312
313         virtual IConfig* getINI() const {return m_ini;}
314
315         static ShibTargetConfig& getConfig();
316
317     protected:
318         IConfig* m_ini;
319     };
320
321     class ShibTargetPriv;
322     class SHIBTARGET_EXPORTS ShibTarget {
323     public:
324         ShibTarget(const IApplication* app);
325         virtual ~ShibTarget(void);
326
327         // These are defined here so the subclass does not need to specifically
328         // depend on log4cpp.  We could use log4cpp::Priority::PriorityLevel
329         // but this is just as easy, IMHO.  It's just a case statement in the
330         // implementation to handle the event level.
331         enum ShibLogLevel {
332           LogLevelDebug,
333           LogLevelInfo,
334           LogLevelWarn,
335           LogLevelError
336         };
337
338         //
339         // Note: subclasses MUST implement ALL of these virtual methods
340         //
341         
342         // Send a message to the Webserver log
343         virtual void log(ShibLogLevel level, const std::string &msg)=0;
344
345         void log(ShibLogLevel level, const char* msg) {
346           std::string s = msg;
347           log(level, s);
348         }
349
350         // Get/Set a cookie for this request
351         virtual std::string getCookies() const=0;
352         virtual void setCookie(const std::string& name, const std::string& value)=0;
353         virtual const char* getCookie(const std::string& name) const;
354         void setCookie(const char* name, const char* value) {
355           std::string ns = name;
356           std::string vs = value;
357           setCookie(ns, vs);
358         }
359         void setCookie(const char* name, const std::string& value) {
360           std::string ns = name;
361           setCookie(ns, value);
362         }
363
364         // Get any URL-encoded arguments or the raw POST body from the server
365         virtual const char* getQueryString() const=0;
366         virtual const char* getRequestBody() const=0;
367         virtual const char* getRequestParameter(const char* param, size_t index=0) const;
368
369         // Clear a header, set a header
370         // These APIs are used for exporting the Assertions into the
371         // Headers.  It will clear some well-known headers first to make
372         // sure none remain.  Then it will process the set of assertions
373         // and export them via setHeader().
374         virtual void clearHeader(const std::string& name)=0;
375         virtual void setHeader(const std::string& name, const std::string& value)=0;
376         virtual std::string getHeader(const std::string& name)=0;
377         virtual void setRemoteUser(const std::string& user)=0;
378         virtual std::string getRemoteUser()=0;
379
380         void clearHeader(const char* n) {
381           std::string s = n;
382           clearHeader(s);
383         }
384         void setHeader(const char* n, const char* v) {
385           std::string ns = n;
386           std::string vs = v;
387           setHeader(ns, vs);
388         }
389         void setHeader(const std::string& n, const char* v) {
390           std::string vs = v;
391           setHeader(n, vs);
392         }
393         void setHeader(const char* n, const std::string& v) {
394           std::string ns = n;
395           setHeader(ns, v);
396         }
397         std::string getHeader(const char* n) {
398           std::string s = n;
399           return getHeader(s);
400         }
401         void setRemoteUser(const char* n) {
402           std::string s = n;
403           setRemoteUser(s);
404         }
405
406         // We're done.  Finish up.  Send specific result content or a redirect.
407         // If there are no headers supplied assume the content-type is text/html
408         typedef std::pair<std::string, std::string> header_t;
409         virtual void* sendPage(
410             const std::string& msg,
411             int code = 200,
412             const std::string& content_type = "text/html",
413             const saml::Iterator<header_t>& headers = EMPTY(header_t)
414             )=0;
415         void* sendPage(const char* msg) {
416           std::string m = msg;
417           return sendPage(m);
418         }
419         virtual void* sendRedirect(const std::string& url)=0;
420         
421         // These next two APIs are used to obtain the module-specific "OK"
422         // and "Decline" results.  OK means "we believe that this request
423         // should be accepted".  Declined means "we believe that this is
424         // not a shibbolized request so we have no comment".
425
426         virtual void* returnDecline();
427         virtual void* returnOK();
428
429         //
430         // Note:  Subclasses need not implement anything below this line
431         //
432
433         // These functions implement the server-agnostic shibboleth engine
434         // The web server modules implement a subclass and then call into 
435         // these methods once they instantiate their request object.
436         // 
437         // Return value:
438         //   these APIs will always return the result of sendPage(), sendRedirect(),
439         //   returnDecline(), or returnOK() in the void* portion of the return code.
440         //   Exactly what those values are is module- (subclass-) implementation
441         //   specific.  The 'bool' part of the return value declares whether the
442         //   void* is valid or not.  If the bool is true then the void* is valid.
443         //   If the bool is false then the API did not call any callback, the void*
444         //   is not valid, and the caller should continue processing (the API Call
445         //   finished successfully).
446         //
447         //   The handleProfile argument declares whether doCheckAuthN() should
448         //   automatically call doHandlePOST() when it encounters a request for
449         //   the ShireURL;  if false it will call returnOK() instead.
450         //
451         std::pair<bool,void*> doCheckAuthN(bool handler = false);
452         std::pair<bool,void*> doHandler();
453         std::pair<bool,void*> doCheckAuthZ();
454         std::pair<bool,void*> doExportAssertions(bool requireSession = true);
455
456         // Basic request access in case any plugins need the info
457         virtual const IConfig* getConfig() const;
458         virtual const IApplication* getApplication() const;
459         const char* getRequestMethod() const {return m_method.c_str();}
460         const char* getProtocol() const {return m_protocol.c_str();}
461         const char* getHostname() const {return m_hostname.c_str();}
462         int getPort() const {return m_port;}
463         const char* getRequestURI() const {return m_uri.c_str();}
464         const char* getContentType() const {return m_content_type.c_str();}
465         const char* getRemoteAddr() const {return m_remote_addr.c_str();}
466         const char* getRequestURL() const {return m_url.c_str();}
467         
468         // Advanced methods useful to profile handlers implemented outside core
469         
470         // Get per-application session and state cookie name and properties
471         virtual std::pair<std::string,const char*> getCookieNameProps(const char* prefix) const;
472         
473         // Determine the effective handler URL based on the resource URL
474         virtual std::string getHandlerURL(const char* resource) const;
475
476     protected:
477         ShibTarget();
478
479         // Internal APIs
480
481         // Initialize the request from the parsed URL
482         // protocol == http, https, etc
483         // hostname == server name
484         // port == server port
485         // uri == resource path
486         // method == GET, POST, etc.
487         void init(
488             const char* protocol,
489             const char* hostname,
490             int port,
491             const char* uri,
492             const char* content_type,
493             const char* remote_addr,
494             const char* method
495             );
496
497         std::string m_url, m_method, m_protocol, m_hostname, m_uri, m_content_type, m_remote_addr;
498         int m_port;
499
500     private:
501         mutable ShibTargetPriv* m_priv;
502         friend class ShibTargetPriv;
503     };
504
505     struct SHIBTARGET_EXPORTS XML
506     {
507         static const XMLCh SHIBTARGET_NS[];
508         static const XMLCh SHIBTARGET_SCHEMA_ID[];
509         static const XMLCh SAML2ASSERT_NS[];
510         static const XMLCh SAML2ASSERT_SCHEMA_ID[];
511         static const XMLCh SAML2META_NS[];
512         static const XMLCh SAML2META_SCHEMA_ID[];
513         static const XMLCh XMLENC_NS[];
514         static const XMLCh XMLENC_SCHEMA_ID[];
515     
516         // Session cache implementations
517         static const char MemorySessionCacheType[];
518         static const char MySQLSessionCacheType[];
519         static const char ODBCSessionCacheType[];
520         
521         // Replay cache implementations
522         static const char MySQLReplayCacheType[];
523         static const char ODBCReplayCacheType[];
524         
525         // Request mapping/settings implementations
526         static const char XMLRequestMapType[];      // portable XML-based map
527         static const char NativeRequestMapType[];   // Native web server command override of XML-based map
528         static const char LegacyRequestMapType[];   // older designation of XML map, hijacked by web server
529         
530         // Access control implementations
531         static const char htAccessControlType[];    // Apache-specific .htaccess authz module
532         static const char XMLAccessControlType[];   // Proprietary but portable XML authz syntax
533
534         struct SHIBTARGET_EXPORTS Literals
535         {
536             static const XMLCh AAPProvider[];
537             static const XMLCh AccessControl[];
538             static const XMLCh AccessControlProvider[];
539             static const XMLCh acl[];
540             static const XMLCh AND[];
541             static const XMLCh applicationId[];
542             static const XMLCh Application[];
543             static const XMLCh Applications[];
544             static const XMLCh AssertionConsumerService[];
545             static const XMLCh AttributeFactory[];
546             static const XMLCh config[];
547             static const XMLCh CredentialsProvider[];
548             static const XMLCh CredentialUse[];
549             static const XMLCh DiagnosticService[];
550             static const XMLCh echo[];
551             static const XMLCh Extensions[];
552             static const XMLCh fatal[];
553             static const XMLCh FederationProvider[];
554             static const XMLCh Global[];
555             static const XMLCh Host[];
556             static const XMLCh htaccess[];
557             static const XMLCh Implementation[];
558             static const XMLCh index[];
559             static const XMLCh InProcess[];
560             static const XMLCh isDefault[];
561             static const XMLCh Library[];
562             static const XMLCh Listener[];
563             static const XMLCh Local[];
564             static const XMLCh log[];
565             static const XMLCh logger[];
566             static const XMLCh MemorySessionCache[];
567             static const XMLCh MetadataProvider[];
568             static const XMLCh MySQLReplayCache[];
569             static const XMLCh MySQLSessionCache[];
570             static const XMLCh name[];
571             static const XMLCh Name[];
572             static const XMLCh NOT[];
573             static const XMLCh ODBCReplayCache[];
574             static const XMLCh ODBCSessionCache[];
575             static const XMLCh OR[];
576             static const XMLCh OutOfProcess[];
577             static const XMLCh Path[];
578             static const XMLCh path[];
579             static const XMLCh RelyingParty[];
580             static const XMLCh ReplayCache[];
581             static const XMLCh RequestMap[];
582             static const XMLCh RequestMapProvider[];
583             static const XMLCh require[];
584             static const XMLCh Rule[];
585             static const XMLCh SessionCache[];
586             static const XMLCh SessionInitiator[];
587             static const XMLCh SHAR[];
588             static const XMLCh ShibbolethTargetConfig[];
589             static const XMLCh SHIRE[];
590             static const XMLCh Signing[];
591             static const XMLCh SingleLogoutService[];
592             static const XMLCh SPConfig[];
593             static const XMLCh TCPListener[];
594             static const XMLCh TLS[];
595             static const XMLCh TrustProvider[];
596             static const XMLCh type[];
597             static const XMLCh UnixListener[];
598         };
599     };
600 }
601
602 #endif /* SHIB_TARGET_H */