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"
72 # include <shib-target/shib-paths.h>
73 # define SHIBTARGET_EXPORTS
76 #include <shib-target/shibrpc.h>
78 namespace shibtarget {
80 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ListenerException,SAMLException);
81 DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ConfigurationException,SAMLException);
83 // Abstract APIs for access to configuration information
85 struct SHIBTARGET_EXPORTS IPropertySet
87 virtual std::pair<bool,bool> getBool(const char* name, const char* ns=NULL) const=0;
88 virtual std::pair<bool,const char*> getString(const char* name, const char* ns=NULL) const=0;
89 virtual std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const=0;
90 virtual std::pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const=0;
91 virtual std::pair<bool,int> getInt(const char* name, const char* ns=NULL) const=0;
92 virtual const IPropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const=0;
93 virtual const DOMElement* getElement() const=0;
94 virtual ~IPropertySet() {}
97 struct SHIBTARGET_EXPORTS IListener : public virtual saml::IPlugIn
100 typedef SOCKET ShibSocket;
102 typedef int ShibSocket;
104 virtual bool create(ShibSocket& s) const=0;
105 virtual bool bind(ShibSocket& s, bool force=false) const=0;
106 virtual bool connect(ShibSocket& s) const=0;
107 virtual bool close(ShibSocket& s) const=0;
108 virtual bool accept(ShibSocket& listener, ShibSocket& s) const=0;
109 virtual CLIENT* getClientHandle(ShibSocket& s, u_long program, u_long version) const=0;
110 virtual ~IListener() {}
113 class SHIBTARGET_EXPORTS ShibTarget;
114 struct SHIBTARGET_EXPORTS IAccessControl : public virtual saml::ILockable, public virtual saml::IPlugIn
116 virtual bool authorized(
117 const char* providerId,
118 const saml::SAMLAuthenticationStatement* authn,
119 const saml::SAMLResponse* attrs,
122 virtual ~IAccessControl() {}
125 struct SHIBTARGET_EXPORTS IRequestMapper : public virtual saml::ILockable, public virtual saml::IPlugIn
127 typedef std::pair<const IPropertySet*,IAccessControl*> Settings;
128 virtual Settings getSettingsFromURL(const char* url, ShibTarget* st) const=0;
129 virtual Settings getSettingsFromParsedURL(
130 const char* scheme, const char* hostname, unsigned int port, const char* path, ShibTarget* st
132 virtual ~IRequestMapper() {}
135 struct SHIBTARGET_EXPORTS IApplication : public virtual IPropertySet
137 virtual const char* getId() const=0;
138 virtual const char* getHash() const=0;
140 virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
141 virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
142 virtual saml::Iterator<shibboleth::IMetadata*> getMetadataProviders() const=0;
143 virtual saml::Iterator<shibboleth::ITrust*> getTrustProviders() const=0;
144 virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
145 virtual const IPropertySet* getCredentialUse(const shibboleth::IEntityDescriptor* provider) const=0;
147 // caller is borrowing object, must use within scope of config lock
148 virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0;
149 virtual const saml::SAMLBinding* getBinding(const XMLCh* binding) const=0;
151 // caller is given ownership of object, must use and delete within scope of config lock
152 virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0;
154 // Used to locate a default or designated session initiator for automatic sessions
155 virtual const IPropertySet* getDefaultSessionInitiator() const=0;
156 virtual const IPropertySet* getSessionInitiatorById(const char* id) const=0;
158 // Used by session initiators to get endpoint to forward to IdP/WAYF
159 virtual const IPropertySet* getDefaultAssertionConsumerService() const=0;
160 virtual const IPropertySet* getAssertionConsumerServiceByIndex(unsigned short index) const=0;
162 // Used by dispatcher to locate a handler for a Shibboleth request
163 virtual const IPropertySet* getHandler(const char* path) const=0;
165 virtual ~IApplication() {}
168 struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
170 virtual bool isValid(time_t lifetime, time_t timeout) const=0;
171 virtual const char* getClientAddress() const=0;
172 virtual ShibProfile getProfile() const=0;
173 virtual const char* getProviderId() const=0;
174 virtual const saml::SAMLAuthenticationStatement* getAuthnStatement() const=0;
175 struct SHIBTARGET_EXPORTS CachedResponse {
176 CachedResponse(const saml::SAMLResponse* unfiltered, const saml::SAMLResponse* filtered) {
177 this->unfiltered=unfiltered;
178 this->filtered=filtered;
180 bool empty() {return unfiltered==NULL;}
181 const saml::SAMLResponse* unfiltered;
182 const saml::SAMLResponse* filtered;
184 virtual CachedResponse getResponse()=0;
185 virtual ~ISessionCacheEntry() {}
188 struct SHIBTARGET_EXPORTS ISessionCache : public virtual saml::IPlugIn
190 virtual void thread_init()=0;
191 virtual void thread_end()=0;
192 virtual std::string generateKey() const=0;
195 const IApplication* application,
196 const char* client_addr,
198 const char* providerId,
199 saml::SAMLAuthenticationStatement* s,
200 saml::SAMLResponse* r=NULL,
201 const shibboleth::IRoleDescriptor* source=NULL,
205 virtual ISessionCacheEntry* find(const char* key, const IApplication* application)=0;
206 virtual void remove(const char* key)=0;
207 virtual ~ISessionCache() {}
210 struct SHIBTARGET_EXPORTS IConfig : public virtual saml::ILockable, public virtual IPropertySet, public virtual saml::IPlugIn
212 virtual const IListener* getListener() const=0;
213 virtual ISessionCache* getSessionCache() const=0;
214 virtual saml::IReplayCache* getReplayCache() const=0;
215 virtual IRequestMapper* getRequestMapper() const=0;
216 virtual const IApplication* getApplication(const char* applicationId) const=0;
217 virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
218 virtual ~IConfig() {}
221 class SHIBTARGET_EXPORTS ShibTargetConfig
224 ShibTargetConfig() : m_ini(NULL), m_features(0) {}
225 virtual ~ShibTargetConfig() {}
227 virtual bool init(const char* schemadir) = 0;
228 virtual bool load(const char* config) = 0;
229 virtual void shutdown() = 0;
239 GlobalExtensions = 128,
240 LocalExtensions = 256,
243 void setFeatures(long enabled) {m_features = enabled;}
244 bool isEnabled(components_t feature) {return (m_features & feature)>0;}
245 virtual IConfig* getINI() const {return m_ini;}
247 static const XMLCh SHIBTARGET_NS[];
248 static ShibTargetConfig& getConfig();
254 unsigned long m_features;
261 for (int k = 0; k < elements.size(); k++)
268 std::vector<std::string> tokens;
270 std::vector<RequireLine*> elements;
276 virtual ~HTGroupTable() {}
277 virtual bool lookup(const char *entry) = 0;
282 class ShibTargetPriv;
283 class SHIBTARGET_EXPORTS ShibTarget {
285 ShibTarget(const IApplication *app);
286 virtual ~ShibTarget(void);
288 // These are defined here so the subclass does not need to specifically
289 // depend on log4cpp. We could use log4cpp::Priority::PriorityLevel
290 // but this is just as easy, IMHO. It's just a case statement in the
291 // implementation to handle the event level.
300 // Note: subclasses MUST implement ALL of these virtual methods
303 // Send a message to the Webserver log
304 virtual void log(ShibLogLevel level, const std::string &msg)=0;
306 void log(ShibLogLevel level, const char *msg) {
311 // Get/Set a cookie for this request
312 virtual std::string getCookies() const=0;
313 virtual void setCookie(const std::string &name, const std::string &value)=0;
314 void setCookie(const char *name, const char *value) {
315 std::string ns = name;
316 std::string vs = value;
319 void setCookie(const char *name, const std::string &value) {
320 std::string ns = name;
321 setCookie(ns, value);
325 // Get the request's GET arguments or POST data from the server
326 virtual std::string getArgs(void)=0;
327 virtual std::string getPostData(void)=0;
329 // Clear a header, set a header
330 // These APIs are used for exporting the Assertions into the
331 // Headers. It will clear some well-known headers first to make
332 // sure none remain. Then it will process the set of assertions
333 // and export them via setHeader().
334 virtual void clearHeader(const std::string &name)=0;
335 virtual void setHeader(const std::string &name, const std::string &value)=0;
336 virtual std::string getHeader(const std::string &name)=0;
337 virtual void setRemoteUser(const std::string &user)=0;
338 virtual std::string getRemoteUser(void)=0;
340 void clearHeader(const char *n) {
344 void setHeader(const char *n, const char *v) {
349 void setHeader(const std::string &n, const char *v) {
353 void setHeader(const char *n, const std::string &v) {
357 std::string getHeader(const char *n) {
361 void setRemoteUser(const char *n) {
366 // returns the "auth type".. if this string is not "shibboleth" then
367 // the request will be denied. Any kind of "override" should be handled
368 // by the subclass before returning this value. Note that the default
369 // implementation always returns "shibboleth".
370 virtual std::string getAuthType(void);
372 // Note: we still need to define exactly what kind of data in contained
373 // in the HTAccessInfo -- perhaps we can stub it out so non-htaccess
374 // systems have something they can plug in?
375 virtual HTAccessInfo* getAccessInfo(void);
376 virtual HTGroupTable* getGroupTable(std::string &user);
378 // We're done. Finish up. Send specific result content or a redirect.
379 // If there are no headers supplied assume the content-type is text/html
380 typedef std::pair<std::string, std::string> header_t;
381 virtual void* sendPage(
382 const std::string& msg,
384 const std::string& content_type = "text/html",
385 const saml::Iterator<header_t>& headers = EMPTY(header_t)
387 void* sendPage(const char *msg) {
391 virtual void* sendRedirect(const std::string& url)=0;
393 // These next two APIs are used to obtain the module-specific "OK"
394 // and "Decline" results. OK means "we believe that this request
395 // should be accepted". Declined means "we believe that this is
396 // not a shibbolized request so we have no comment".
398 virtual void* returnDecline(void);
399 virtual void* returnOK(void);
402 // Note: Subclasses need not implement anything below this line
405 // These functions implement the server-agnostic shibboleth engine
406 // The web server modules implement a subclass and then call into
407 // these methods once they instantiate their request object.
410 // these APIs will always return the result of sendPage(), sendRedirect(),
411 // returnDecline(), or returnOK() in the void* portion of the return code.
412 // Exactly what those values are is module- (subclass-) implementation
413 // specific. The 'bool' part of the return value declares whether the
414 // void* is valid or not. If the bool is true then the void* is valid.
415 // If the bool is false then the API did not call any callback, the void*
416 // is not valid, and the caller should continue processing (the API Call
417 // finished successfully).
419 // The arguments are all overrides.. The requireSession and
420 // exportAssertion values passed in here are only used if the
421 // settings resource is negative.
423 // The handleProfile argument declares whether doCheckAuthN() should
424 // automatically call doHandlePOST() when it encounters a request for
425 // the ShireURL; if false it will call returnOK() instead.
427 std::pair<bool,void*> doCheckAuthN(bool requireSession = false, bool handler = false);
428 std::pair<bool,void*> doHandler();
429 std::pair<bool,void*> doCheckAuthZ();
430 std::pair<bool,void*> doExportAssertions(bool exportAssertion = false);
432 // Currently wraps remoted interface.
433 // TODO: Move this functionality behind IListener
435 int supported_profiles,
436 const std::string& recipient,
441 std::string& provider_id
447 ShibProfile& profile,
448 std::string& provider_id,
449 saml::SAMLAuthenticationStatement** auth_statement=NULL,
450 saml::SAMLResponse** attr_response_pre=NULL,
451 saml::SAMLResponse** attr_response_post=NULL
454 void sessionEnd(const char* cookie) const;
456 // Basic request access in case any plugins need the info
457 const char* getRequestMethod() const {return m_method.c_str();}
458 const char* getProtocol() const {return m_protocol.c_str();}
459 const char* getHostname() const {return m_hostname.c_str();}
460 int getPort() const {return m_port;}
461 const char* getRequestURI() const {return m_uri.c_str();}
462 const char* getContentType() const {return m_content_type.c_str();}
463 const char* getRemoteAddr() const {return m_remote_addr.c_str();}
464 const char* getRequestURL() const {return m_url.c_str();}
471 // Initialize the request from the parsed URL
472 // protocol == http, https, etc
473 // hostname == server name
474 // port == server port
475 // uri == resource path
476 // method == GET, POST, etc.
478 const char* protocol,
479 const char* hostname,
482 const char* content_type,
483 const char* remote_addr,
487 std::string m_url, m_method, m_protocol, m_hostname, m_uri, m_content_type, m_remote_addr;
491 mutable ShibTargetPriv* m_priv;
492 friend class ShibTargetPriv;
496 #endif /* SHIB_TARGET_H */