2 * Copyright 2001-2005 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * shib-target.h -- top-level header file for the SHIB Common Target Library
20 * Created by: Derek Atkins <derek@ihtfp.com>
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>
36 #include <saml/saml.h>
37 #include <shib/shib.h>
40 # ifndef SHIBTARGET_EXPORTS
41 # define SHIBTARGET_EXPORTS __declspec(dllimport)
43 # define SHIB_SCHEMAS "/opt/shibboleth-sp/share/xml/shibboleth"
44 # define SHIB_CONFIG "/opt/shibboleth-sp/etc/shibboleth/shibboleth.xml"
46 # include <shib-target/shib-paths.h>
47 # define SHIBTARGET_EXPORTS
50 namespace shibtarget {
52 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ListenerException,SAMLException);
53 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ConfigurationException,SAMLException);
55 // Abstract APIs for access to configuration information
57 // Forward declaration
58 class SHIBTARGET_EXPORTS ShibTarget;
61 * Interface to a protocol handler
63 * Protocol handlers perform system functions such as processing SAML protocol
64 * messages to create and logout sessions or creating protocol requests.
66 struct SHIBTARGET_EXPORTS IHandler : public virtual saml::IPlugIn
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;
74 const shibsp::PropertySet* m_props;
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.
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"
88 struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::PropertySet,
89 public virtual shibboleth::ShibBrowserProfile::ITokenValidator
91 virtual const char* getId() const=0;
92 virtual const char* getHash() const=0;
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;
101 virtual const opensaml::saml2md::MetadataProvider* getMetadataProvider() const=0;
102 virtual const xmltooling::TrustEngine* getTrustEngine() const=0;
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;
108 // caller is given ownership of object, must use and delete within scope of config lock
109 virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0;
111 // general token validation based on conditions, signatures, etc.
112 virtual void validateToken(
113 saml::SAMLAssertion* token,
115 const shibboleth::IRoleDescriptor* role=NULL,
116 const saml::Iterator<shibboleth::ITrust*>& trusts=EMPTY(shibboleth::ITrust*)
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;
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;
128 // Used by dispatcher to locate the handler for a request
129 virtual const IHandler* getHandler(const char* path) const=0;
131 virtual ~IApplication() {}
135 * OpenSAML binding hook
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.
142 class ShibHTTPHook : virtual public saml::SAMLSOAPHTTPBinding::HTTPHook
145 ShibHTTPHook(const saml::Iterator<shibboleth::ITrust*>& trusts, const saml::Iterator<shibboleth::ICredentials*>& creds)
146 : m_trusts(trusts), m_creds(creds) {}
147 virtual ~ShibHTTPHook() {}
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);
152 // Client declares a context object and pass as callCtx to send() method.
153 class ShibHTTPHookCallContext {
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;}
164 const shibsp::PropertySet* m_credUse;
165 const shibboleth::IRoleDescriptor* m_role;
166 ShibHTTPHook* m_hook;
167 bool m_authenticated;
168 friend class ShibHTTPHook;
171 const saml::Iterator<shibboleth::ITrust*>& getTrustProviders() const {return m_trusts;}
172 const saml::Iterator<shibboleth::ICredentials*>& getCredentialProviders() const {return m_creds;}
174 saml::Iterator<shibboleth::ITrust*> m_trusts;
175 saml::Iterator<shibboleth::ICredentials*> m_creds;
179 * Interface to a cached user session.
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.
186 struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
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() {}
198 * Interface to a sink for session cache events.
200 * All caches support registration of a backing store that can be informed
201 * of significant events in the lifecycle of a cache entry.
203 struct SHIBTARGET_EXPORTS ISessionCacheStore
205 virtual HRESULT onCreate(
207 const IApplication* application,
208 const ISessionCacheEntry* entry,
213 virtual HRESULT onRead(
215 std::string& applicationId,
216 std::string& clientAddress,
217 std::string& providerId,
218 std::string& subject,
219 std::string& authnContext,
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() {}
234 * Interface to the session cache.
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.
242 struct SHIBTARGET_EXPORTS ISessionCache : public virtual saml::IPlugIn
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
252 virtual ISessionCacheEntry* find(
253 const char* key, const IApplication* application, const char* client_addr
256 const char* key, const IApplication* application, const char* client_addr
259 virtual bool setBackingStore(ISessionCacheStore* store)=0;
260 virtual ~ISessionCache() {}
264 * Interface to an access control plugin
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.
270 struct SHIBTARGET_EXPORTS IAccessControl : public virtual saml::ILockable, public virtual saml::IPlugIn
272 virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const=0;
273 virtual ~IAccessControl() {}
277 * Interface to a request mapping plugin
279 * Request mapping plugins return configuration settings that apply to resource requests.
280 * They can be implemented through cross-platform or platform-specific mechanisms.
282 struct SHIBTARGET_EXPORTS IRequestMapper : public virtual saml::ILockable, public virtual saml::IPlugIn
284 typedef std::pair<const shibsp::PropertySet*,IAccessControl*> Settings;
285 virtual Settings getSettings(ShibTarget* st) const=0;
286 virtual ~IRequestMapper() {}
289 struct SHIBTARGET_EXPORTS IConfig : public virtual saml::ILockable, public virtual shibsp::PropertySet, public virtual saml::IPlugIn
291 // loads initial configuration
292 virtual void init()=0;
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() {}
303 class SHIBTARGET_EXPORTS ShibTargetConfig
306 ShibTargetConfig() : m_ini(NULL) {}
307 virtual ~ShibTargetConfig() {}
309 virtual bool init(const char* schemadir) = 0;
310 virtual bool load(const char* config) = 0;
311 virtual void shutdown() = 0;
313 virtual IConfig* getINI() const {return m_ini;}
315 static ShibTargetConfig& getConfig();
321 class ShibTargetPriv;
322 class SHIBTARGET_EXPORTS ShibTarget {
324 ShibTarget(const IApplication* app);
325 virtual ~ShibTarget(void);
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.
339 // Note: subclasses MUST implement ALL of these virtual methods
342 // Send a message to the Webserver log
343 virtual void log(ShibLogLevel level, const std::string &msg)=0;
345 void log(ShibLogLevel level, const char* msg) {
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;
359 void setCookie(const char* name, const std::string& value) {
360 std::string ns = name;
361 setCookie(ns, value);
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;
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;
380 void clearHeader(const char* n) {
384 void setHeader(const char* n, const char* v) {
389 void setHeader(const std::string& n, const char* v) {
393 void setHeader(const char* n, const std::string& v) {
397 std::string getHeader(const char* n) {
401 void setRemoteUser(const char* n) {
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,
412 const std::string& content_type = "text/html",
413 const saml::Iterator<header_t>& headers = EMPTY(header_t)
415 void* sendPage(const char* msg) {
419 virtual void* sendRedirect(const std::string& url)=0;
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".
426 virtual void* returnDecline();
427 virtual void* returnOK();
430 // Note: Subclasses need not implement anything below this line
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.
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).
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.
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);
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();}
468 // Advanced methods useful to profile handlers implemented outside core
470 // Get per-application session and state cookie name and properties
471 virtual std::pair<std::string,const char*> getCookieNameProps(const char* prefix) const;
473 // Determine the effective handler URL based on the resource URL
474 virtual std::string getHandlerURL(const char* resource) const;
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.
488 const char* protocol,
489 const char* hostname,
492 const char* content_type,
493 const char* remote_addr,
497 std::string m_url, m_method, m_protocol, m_hostname, m_uri, m_content_type, m_remote_addr;
501 mutable ShibTargetPriv* m_priv;
502 friend class ShibTargetPriv;
505 struct SHIBTARGET_EXPORTS XML
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[];
516 // Session cache implementations
517 static const char MemorySessionCacheType[];
518 static const char MySQLSessionCacheType[];
519 static const char ODBCSessionCacheType[];
521 // Replay cache implementations
522 static const char MySQLReplayCacheType[];
523 static const char ODBCReplayCacheType[];
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
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
534 struct SHIBTARGET_EXPORTS Literals
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[];
602 #endif /* SHIB_TARGET_H */