2 * The Shibboleth License, Version 1.
4 * University Corporation for Advanced Internet Development, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution, if any, must include
17 * the following acknowledgment: "This product includes software developed by
18 * the University Corporation for Advanced Internet Development
19 * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20 * may appear in the software itself, if and wherever such third-party
21 * acknowledgments normally appear.
23 * Neither the name of Shibboleth nor the names of its contributors, nor
24 * Internet2, nor the University Corporation for Advanced Internet Development,
25 * Inc., nor UCAID may be used to endorse or promote products derived from this
26 * software without specific prior written permission. For written permission,
27 * please contact shibboleth@shibboleth.org
29 * Products derived from this software may not be called Shibboleth, Internet2,
30 * UCAID, or the University Corporation for Advanced Internet Development, nor
31 * may Shibboleth appear in their name, without prior written permission of the
32 * University Corporation for Advanced Internet Development.
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39 * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40 * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41 * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 * shib-target.h -- top-level header file for the SHIB Common Target Library
53 * Created by: Derek Atkins <derek@ihtfp.com>
61 #include <saml/saml.h>
62 #include <shib/shib.h>
63 #include <shib/shib-threads.h>
66 # ifndef SHIBTARGET_EXPORTS
67 # define SHIBTARGET_EXPORTS __declspec(dllimport)
69 # define SHIB_SCHEMAS "/opt/shibboleth/share/xml/shibboleth"
70 # define SHIB_CONFIG "/opt/shibboleth/etc/shibboleth/shibboleth.xml"
73 # include <shib-target/shib-paths.h>
74 # define SHIBTARGET_EXPORTS
78 namespace shibtarget {
80 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ListenerException,SAMLException);
81 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ConfigurationException,SAMLException);
84 PROFILE_UNSPECIFIED = 0,
92 // Abstract APIs for access to configuration information
94 struct SHIBTARGET_EXPORTS IPropertySet
96 virtual std::pair<bool,bool> getBool(const char* name, const char* ns=NULL) const=0;
97 virtual std::pair<bool,const char*> getString(const char* name, const char* ns=NULL) const=0;
98 virtual std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const=0;
99 virtual std::pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const=0;
100 virtual std::pair<bool,int> getInt(const char* name, const char* ns=NULL) const=0;
101 virtual const IPropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const=0;
102 virtual const DOMElement* getElement() const=0;
103 virtual ~IPropertySet() {}
106 struct SHIBTARGET_EXPORTS IApplication : public virtual IPropertySet
108 virtual const char* getId() const=0;
109 virtual const char* getHash() const=0;
111 virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
112 virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
113 virtual saml::Iterator<shibboleth::IMetadata*> getMetadataProviders() const=0;
114 virtual saml::Iterator<shibboleth::ITrust*> getTrustProviders() const=0;
115 virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
116 virtual const IPropertySet* getCredentialUse(const shibboleth::IEntityDescriptor* provider) const=0;
118 // caller is borrowing object, must use within scope of config lock
119 virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0;
120 virtual const saml::SAMLBinding* getBinding(const XMLCh* binding) const=0;
122 // caller is given ownership of object, must use and delete within scope of config lock
123 virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0;
125 // Used to locate a default or designated session initiator for automatic sessions
126 virtual const IPropertySet* getDefaultSessionInitiator() const=0;
127 virtual const IPropertySet* getSessionInitiatorById(const char* id) const=0;
129 // Used by session initiators to get endpoint to forward to IdP/WAYF
130 virtual const IPropertySet* getDefaultAssertionConsumerService() const=0;
131 virtual const IPropertySet* getAssertionConsumerServiceByIndex(unsigned short index) const=0;
133 // Used by dispatcher to locate the handler configuration for a Shibboleth request
134 virtual const IPropertySet* getHandlerConfig(const char* path) const=0;
136 virtual ~IApplication() {}
139 // Instead of wrapping the binding to deal with mutual authentication, we
140 // just use the HTTP hook functionality offered by OpenSAML. The hook will
141 // register "itself" as a globalCtx pointer with the SAML binding and the caller
142 // will declare and pass the embedded struct as callCtx for use by the hook.
143 class ShibHTTPHook : virtual public saml::SAMLSOAPHTTPBinding::HTTPHook
146 ShibHTTPHook(const saml::Iterator<shibboleth::ITrust*>& trusts, const saml::Iterator<shibboleth::ICredentials*>& creds)
147 : m_trusts(trusts), m_creds(creds) {}
148 virtual ~ShibHTTPHook() {}
150 // Only hook we need here is for outgoing connection to server.
151 virtual bool outgoing(saml::HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL);
153 // Client declares a context object and pass as callCtx to send() method.
154 class ShibHTTPHookCallContext {
156 ShibHTTPHookCallContext(const IPropertySet* credUse, const shibboleth::IRoleDescriptor* role)
157 : m_credUse(credUse), m_role(role), m_hook(NULL), m_authenticated(false) {}
158 const ShibHTTPHook* getHook() {return m_hook;}
159 const IPropertySet* getCredentialUse() {return m_credUse;}
160 const shibboleth::IRoleDescriptor* getRoleDescriptor() {return m_role;}
161 bool isAuthenticated() const {return m_authenticated;}
162 void setAuthenticated() {m_authenticated=true;}
165 const IPropertySet* m_credUse;
166 const shibboleth::IRoleDescriptor* m_role;
167 ShibHTTPHook* m_hook;
168 bool m_authenticated;
169 friend class ShibHTTPHook;
172 const saml::Iterator<shibboleth::ITrust*>& getTrustProviders() const {return m_trusts;}
173 const saml::Iterator<shibboleth::ICredentials*>& getCredentialProviders() const {return m_creds;}
175 saml::Iterator<shibboleth::ITrust*> m_trusts;
176 saml::Iterator<shibboleth::ICredentials*> m_creds;
179 struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
181 virtual bool isValid(time_t lifetime, time_t timeout) const=0;
182 virtual const char* getClientAddress() const=0;
183 virtual ShibProfile getProfile() const=0;
184 virtual const char* getProviderId() const=0;
185 virtual const saml::SAMLAuthenticationStatement* getAuthnStatement() const=0;
186 struct SHIBTARGET_EXPORTS CachedResponse {
187 CachedResponse(const saml::SAMLResponse* unfiltered, const saml::SAMLResponse* filtered) {
188 this->unfiltered=unfiltered;
189 this->filtered=filtered;
191 bool empty() {return unfiltered==NULL;}
192 const saml::SAMLResponse* unfiltered;
193 const saml::SAMLResponse* filtered;
195 virtual CachedResponse getResponse()=0;
196 virtual ~ISessionCacheEntry() {}
199 struct SHIBTARGET_EXPORTS ISessionCache : public virtual saml::IPlugIn
201 virtual void thread_init()=0;
202 virtual void thread_end()=0;
203 virtual std::string generateKey() const=0;
206 const IApplication* application,
207 const char* client_addr,
209 const char* providerId,
210 saml::SAMLAuthenticationStatement* s,
211 saml::SAMLResponse* r=NULL,
212 const shibboleth::IRoleDescriptor* source=NULL,
216 virtual ISessionCacheEntry* find(const char* key, const IApplication* application)=0;
217 virtual void remove(const char* key)=0;
218 virtual ~ISessionCache() {}
221 struct SHIBTARGET_EXPORTS IListener : public virtual saml::IPlugIn
223 // The socket APIs should really be somewhere else, but compatibility
224 // with older configuration files dictates that the Listener handles
225 // both client and server socket handling. We can fix this for 2.0...?
227 typedef SOCKET ShibSocket;
229 typedef int ShibSocket;
231 virtual bool create(ShibSocket& s) const=0;
232 virtual bool bind(ShibSocket& s, bool force=false) const=0;
233 virtual bool connect(ShibSocket& s) const=0;
234 virtual bool close(ShibSocket& s) const=0;
235 virtual bool accept(ShibSocket& listener, ShibSocket& s) const=0;
237 // The "real" Listener API abstracts the primitive operations that make up
238 // the meat of the SP's job. Right now, that's session create/read/delete.
239 virtual void sessionNew(
240 const IApplication* application,
241 int supported_profiles,
242 const char* recipient,
247 std::string& provider_id
250 virtual void sessionGet(
251 const IApplication* application,
254 ISessionCacheEntry** pentry
257 virtual void sessionEnd(
258 const IApplication* application,
262 virtual void ping(int& i) const=0;
264 virtual ~IListener() {}
267 class SHIBTARGET_EXPORTS ShibTarget;
269 struct SHIBTARGET_EXPORTS IAccessControl : public virtual saml::ILockable, public virtual saml::IPlugIn
271 virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const=0;
272 virtual ~IAccessControl() {}
275 struct SHIBTARGET_EXPORTS IRequestMapper : public virtual saml::ILockable, public virtual saml::IPlugIn
277 typedef std::pair<const IPropertySet*,IAccessControl*> Settings;
278 virtual Settings getSettings(ShibTarget* st) const=0;
279 virtual ~IRequestMapper() {}
282 struct SHIBTARGET_EXPORTS IHandler : public virtual saml::IPlugIn
284 virtual std::pair<bool,void*> run(ShibTarget* st, const IPropertySet* config, bool isHandler=true)=0;
285 virtual ~IHandler() {}
288 struct SHIBTARGET_EXPORTS IConfig : public virtual saml::ILockable, public virtual IPropertySet, public virtual saml::IPlugIn
290 virtual const IListener* getListener() const=0;
291 virtual ISessionCache* getSessionCache() const=0;
292 virtual saml::IReplayCache* getReplayCache() const=0;
293 virtual IRequestMapper* getRequestMapper() const=0;
294 virtual const IApplication* getApplication(const char* applicationId) const=0;
295 virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
296 virtual ~IConfig() {}
299 class SHIBTARGET_EXPORTS ShibTargetConfig
302 ShibTargetConfig() : m_ini(NULL), m_features(0) {}
303 virtual ~ShibTargetConfig() {}
305 virtual bool init(const char* schemadir) = 0;
306 virtual bool load(const char* config) = 0;
307 virtual void shutdown() = 0;
317 GlobalExtensions = 128,
318 LocalExtensions = 256,
321 void setFeatures(long enabled) {m_features = enabled;}
322 bool isEnabled(components_t feature) {return (m_features & feature)>0;}
323 virtual IConfig* getINI() const {return m_ini;}
325 static ShibTargetConfig& getConfig();
331 unsigned long m_features;
334 class ShibTargetPriv;
335 class SHIBTARGET_EXPORTS ShibTarget {
337 ShibTarget(const IApplication *app);
338 virtual ~ShibTarget(void);
340 // These are defined here so the subclass does not need to specifically
341 // depend on log4cpp. We could use log4cpp::Priority::PriorityLevel
342 // but this is just as easy, IMHO. It's just a case statement in the
343 // implementation to handle the event level.
352 // Note: subclasses MUST implement ALL of these virtual methods
355 // Send a message to the Webserver log
356 virtual void log(ShibLogLevel level, const std::string &msg)=0;
358 void log(ShibLogLevel level, const char *msg) {
363 // Get/Set a cookie for this request
364 virtual std::string getCookies() const=0;
365 virtual void setCookie(const std::string &name, const std::string &value)=0;
366 virtual const char* getCookie(const std::string& name) const;
367 void setCookie(const char *name, const char *value) {
368 std::string ns = name;
369 std::string vs = value;
372 void setCookie(const char *name, const std::string &value) {
373 std::string ns = name;
374 setCookie(ns, value);
378 // Get the request's GET arguments or POST data from the server
379 virtual std::string getArgs(void)=0;
380 virtual std::string getPostData(void)=0;
382 // Clear a header, set a header
383 // These APIs are used for exporting the Assertions into the
384 // Headers. It will clear some well-known headers first to make
385 // sure none remain. Then it will process the set of assertions
386 // and export them via setHeader().
387 virtual void clearHeader(const std::string &name)=0;
388 virtual void setHeader(const std::string &name, const std::string &value)=0;
389 virtual std::string getHeader(const std::string &name)=0;
390 virtual void setRemoteUser(const std::string &user)=0;
391 virtual std::string getRemoteUser(void)=0;
393 void clearHeader(const char *n) {
397 void setHeader(const char *n, const char *v) {
402 void setHeader(const std::string &n, const char *v) {
406 void setHeader(const char *n, const std::string &v) {
410 std::string getHeader(const char *n) {
414 void setRemoteUser(const char *n) {
419 // We're done. Finish up. Send specific result content or a redirect.
420 // If there are no headers supplied assume the content-type is text/html
421 typedef std::pair<std::string, std::string> header_t;
422 virtual void* sendPage(
423 const std::string& msg,
425 const std::string& content_type = "text/html",
426 const saml::Iterator<header_t>& headers = EMPTY(header_t)
428 void* sendPage(const char *msg) {
432 virtual void* sendRedirect(const std::string& url)=0;
434 // These next two APIs are used to obtain the module-specific "OK"
435 // and "Decline" results. OK means "we believe that this request
436 // should be accepted". Declined means "we believe that this is
437 // not a shibbolized request so we have no comment".
439 virtual void* returnDecline(void);
440 virtual void* returnOK(void);
443 // Note: Subclasses need not implement anything below this line
446 // These functions implement the server-agnostic shibboleth engine
447 // The web server modules implement a subclass and then call into
448 // these methods once they instantiate their request object.
451 // these APIs will always return the result of sendPage(), sendRedirect(),
452 // returnDecline(), or returnOK() in the void* portion of the return code.
453 // Exactly what those values are is module- (subclass-) implementation
454 // specific. The 'bool' part of the return value declares whether the
455 // void* is valid or not. If the bool is true then the void* is valid.
456 // If the bool is false then the API did not call any callback, the void*
457 // is not valid, and the caller should continue processing (the API Call
458 // finished successfully).
460 // The handleProfile argument declares whether doCheckAuthN() should
461 // automatically call doHandlePOST() when it encounters a request for
462 // the ShireURL; if false it will call returnOK() instead.
464 std::pair<bool,void*> doCheckAuthN(bool handler = false);
465 std::pair<bool,void*> doHandler();
466 std::pair<bool,void*> doCheckAuthZ();
467 std::pair<bool,void*> doExportAssertions(bool requireSession = true);
469 // Basic request access in case any plugins need the info
470 virtual const IConfig* getConfig() const;
471 virtual const IApplication* getApplication() const;
472 const char* getRequestMethod() const {return m_method.c_str();}
473 const char* getProtocol() const {return m_protocol.c_str();}
474 const char* getHostname() const {return m_hostname.c_str();}
475 int getPort() const {return m_port;}
476 const char* getRequestURI() const {return m_uri.c_str();}
477 const char* getContentType() const {return m_content_type.c_str();}
478 const char* getRemoteAddr() const {return m_remote_addr.c_str();}
479 const char* getRequestURL() const {return m_url.c_str();}
481 // Advanced methods useful to profile handlers implemented outside core
483 // Get per-application session and state cookie name and properties
484 virtual std::pair<std::string,const char*> getCookieNameProps(const char* prefix) const;
486 // Determine the effective handler URL based on the resource URL
487 virtual std::string getHandlerURL(const char* resource) const;
494 // Initialize the request from the parsed URL
495 // protocol == http, https, etc
496 // hostname == server name
497 // port == server port
498 // uri == resource path
499 // method == GET, POST, etc.
501 const char* protocol,
502 const char* hostname,
505 const char* content_type,
506 const char* remote_addr,
510 std::string m_url, m_method, m_protocol, m_hostname, m_uri, m_content_type, m_remote_addr;
514 mutable ShibTargetPriv* m_priv;
515 friend class ShibTargetPriv;
518 struct SHIBTARGET_EXPORTS XML
520 static const XMLCh SHIBTARGET_NS[];
521 static const XMLCh SHIBTARGET_SCHEMA_ID[];
522 static const XMLCh SAML2ASSERT_NS[];
523 static const XMLCh SAML2ASSERT_SCHEMA_ID[];
524 static const XMLCh SAML2META_NS[];
525 static const XMLCh SAML2META_SCHEMA_ID[];
526 static const XMLCh XMLENC_NS[];
527 static const XMLCh XMLENC_SCHEMA_ID[];
529 // Session cache implementations
530 static const char MemorySessionCacheType[];
531 static const char MySQLSessionCacheType[];
533 // Replay cache implementations
534 static const char MySQLReplayCacheType[];
536 // Request mapping/settings implementations
537 static const char XMLRequestMapType[]; // portable XML-based map
538 static const char NativeRequestMapType[]; // Native web server command override of XML-based map
539 static const char LegacyRequestMapType[]; // older designation of XML map, hijacked by web server
541 // Access control implementations
542 static const char htAccessControlType[]; // Apache-specific .htaccess authz module
543 static const char XMLAccessControlType[]; // Proprietary but portable XML authz syntax
545 // Listener implementations
546 static const char TCPListenerType[]; // ONC RPC via TCP socket
547 static const char UnixListenerType[]; // ONC RPC via domain socker
548 static const char MemoryListenerType[]; // "faked" in-process marshalling
550 struct SHIBTARGET_EXPORTS Literals
552 static const XMLCh AAPProvider[];
553 static const XMLCh AccessControl[];
554 static const XMLCh AccessControlProvider[];
555 static const XMLCh acl[];
556 static const XMLCh AND[];
557 static const XMLCh applicationId[];
558 static const XMLCh Application[];
559 static const XMLCh Applications[];
560 static const XMLCh AssertionConsumerService[];
561 static const XMLCh AttributeFactory[];
562 static const XMLCh config[];
563 static const XMLCh CredentialsProvider[];
564 static const XMLCh CredentialUse[];
565 static const XMLCh DiagnosticService[];
566 static const XMLCh echo[];
567 static const XMLCh Extensions[];
568 static const XMLCh fatal[];
569 static const XMLCh FederationProvider[];
570 static const XMLCh Global[];
571 static const XMLCh Host[];
572 static const XMLCh htaccess[];
573 static const XMLCh Implementation[];
574 static const XMLCh index[];
575 static const XMLCh isDefault[];
576 static const XMLCh Library[];
577 static const XMLCh Listener[];
578 static const XMLCh Local[];
579 static const XMLCh log[];
580 static const XMLCh logger[];
581 static const XMLCh MemorySessionCache[];
582 static const XMLCh MetadataProvider[];
583 static const XMLCh MySQLReplayCache[];
584 static const XMLCh MySQLSessionCache[];
585 static const XMLCh name[];
586 static const XMLCh Name[];
587 static const XMLCh NOT[];
588 static const XMLCh OR[];
589 static const XMLCh Path[];
590 static const XMLCh path[];
591 static const XMLCh RelyingParty[];
592 static const XMLCh ReplayCache[];
593 static const XMLCh RequestMap[];
594 static const XMLCh RequestMapProvider[];
595 static const XMLCh require[];
596 static const XMLCh Rule[];
597 static const XMLCh SessionCache[];
598 static const XMLCh SessionInitiator[];
599 static const XMLCh SHAR[];
600 static const XMLCh ShibbolethTargetConfig[];
601 static const XMLCh SHIRE[];
602 static const XMLCh Signing[];
603 static const XMLCh SingleLogoutService[];
604 static const XMLCh SPConfig[];
605 static const XMLCh TCPListener[];
606 static const XMLCh TLS[];
607 static const XMLCh TrustProvider[];
608 static const XMLCh type[];
609 static const XMLCh UnixListener[];
614 #endif /* SHIB_TARGET_H */