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/etc/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 //******************************************************************************
81 // You probably don't care about much below this line
82 // unless you are using the lower-layer APIs provided by
83 // the shib target library. Go to the end of the file to
84 // find the ShibTarget class -- you probably wnat to use that.
87 class SHIBTARGET_EXPORTS ShibTargetException : public std::exception
90 explicit ShibTargetException() : m_code(SHIBRPC_OK) {}
91 explicit ShibTargetException(ShibRpcStatus code, const char* msg, const shibboleth::IEntityDescriptor* provider);
92 explicit ShibTargetException(ShibRpcStatus code, const char* msg, const shibboleth::IRoleDescriptor* role=NULL);
94 virtual ~ShibTargetException() throw () {}
95 virtual ShibRpcStatus which() const throw () { return m_code; }
96 virtual const char* what() const throw () { return m_msg.c_str(); }
97 virtual const char* syswho() const throw() { return m_providerId.c_str(); }
98 virtual const char* where() const throw () { return m_errorURL.c_str(); }
99 virtual const char* who() const throw () { return m_contact.c_str(); }
100 virtual const char* how() const throw () { return m_email.c_str(); }
103 ShibRpcStatus m_code;
105 std::string m_providerId;
106 std::string m_errorURL;
107 std::string m_contact;
112 class SHIBTARGET_EXPORTS RPCError
116 RPCError(ShibRpcError* e);
117 RPCError(int s, const char* st);
118 RPCError(ShibTargetException &exp);
124 // Return a set of strings that correspond to the error properties
125 const char* getType();
126 const char* getText();
127 const char* getDesc();
128 const char* getProviderId();
129 const char* getErrorURL();
130 const char* getContactName();
131 const char* getContactEmail();
135 RPCErrorPriv* m_priv;
138 // Abstract APIs for access to configuration information
140 struct SHIBTARGET_EXPORTS IPropertySet
142 virtual std::pair<bool,bool> getBool(const char* name, const char* ns=NULL) const=0;
143 virtual std::pair<bool,const char*> getString(const char* name, const char* ns=NULL) const=0;
144 virtual std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const=0;
145 virtual std::pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const=0;
146 virtual std::pair<bool,int> getInt(const char* name, const char* ns=NULL) const=0;
147 virtual const IPropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const=0;
148 virtual const DOMElement* getElement() const=0;
149 virtual ~IPropertySet() {}
152 struct SHIBTARGET_EXPORTS IListener : public virtual shibboleth::IPlugIn
155 typedef SOCKET ShibSocket;
157 typedef int ShibSocket;
159 virtual bool create(ShibSocket& s) const=0;
160 virtual bool bind(ShibSocket& s, bool force=false) const=0;
161 virtual bool connect(ShibSocket& s) const=0;
162 virtual bool close(ShibSocket& s) const=0;
163 virtual bool accept(ShibSocket& listener, ShibSocket& s) const=0;
164 virtual CLIENT* getClientHandle(ShibSocket& s, u_long program, u_long version) const=0;
165 virtual ~IListener() {}
168 struct SHIBTARGET_EXPORTS IAccessControl : public virtual shibboleth::ILockable, public virtual shibboleth::IPlugIn
170 virtual bool authorized(
171 const saml::SAMLAuthenticationStatement& authn, const saml::Iterator<saml::SAMLAssertion*>& attrs
173 virtual ~IAccessControl() {}
176 struct SHIBTARGET_EXPORTS IRequestMapper : public virtual shibboleth::ILockable, public virtual shibboleth::IPlugIn
178 typedef std::pair<const IPropertySet*,IAccessControl*> Settings;
179 virtual Settings getSettingsFromURL(const char* url) const=0;
180 virtual Settings getSettingsFromParsedURL(
181 const char* scheme, const char* hostname, unsigned int port, const char* path=NULL
183 virtual ~IRequestMapper() {}
186 struct SHIBTARGET_EXPORTS IApplication : public virtual IPropertySet
188 virtual const char* getId() const=0;
189 virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
190 virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
191 virtual saml::Iterator<shibboleth::IMetadata*> getMetadataProviders() const=0;
192 virtual saml::Iterator<shibboleth::ITrust*> getTrustProviders() const=0;
193 virtual saml::Iterator<shibboleth::IRevocation*> getRevocationProviders() const=0;
194 virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
195 virtual const char* getTLSCred(const shibboleth::IEntityDescriptor* provider) const=0;
196 virtual const char* getSigningCred(const shibboleth::IEntityDescriptor* provider) const=0;
197 virtual ~IApplication() {}
200 struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual shibboleth::ILockable
202 virtual bool isValid(time_t lifetime, time_t timeout) const=0;
203 virtual const char* getClientAddress() const=0;
204 virtual const char* getSerializedStatement() const=0;
205 virtual const saml::SAMLAuthenticationStatement* getStatement() const=0;
206 virtual void preFetch(int prefetch_window)=0;
207 virtual saml::Iterator<saml::SAMLAssertion*> getAssertions()=0;
208 virtual ~ISessionCacheEntry() {}
211 struct SHIBTARGET_EXPORTS ISessionCache : public virtual shibboleth::IPlugIn
213 virtual void thread_init()=0;
214 virtual void thread_end()=0;
215 virtual std::string generateKey() const=0;
218 const IApplication* application,
219 saml::SAMLAuthenticationStatement *s,
220 const char* client_addr,
221 saml::SAMLResponse* r=NULL,
222 const shibboleth::IRoleDescriptor* source=NULL
224 virtual ISessionCacheEntry* find(const char* key, const IApplication* application)=0;
225 virtual void remove(const char* key)=0;
226 virtual ~ISessionCache() {}
229 struct SHIBTARGET_EXPORTS IConfig : public virtual shibboleth::ILockable, public virtual IPropertySet, public virtual shibboleth::IPlugIn
231 virtual const IListener* getListener() const=0;
232 virtual ISessionCache* getSessionCache() const=0;
233 virtual IRequestMapper* getRequestMapper() const=0;
234 virtual const IApplication* getApplication(const char* applicationId) const=0;
235 virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
236 virtual ~IConfig() {}
239 class SHIBTARGET_EXPORTS ShibTargetConfig
242 ShibTargetConfig() : m_ini(NULL), m_features(0) {}
243 virtual ~ShibTargetConfig() {}
245 virtual bool init(const char* schemadir, const char* config) = 0;
246 virtual void shutdown() = 0;
256 SHARExtensions = 128,
257 SHIREExtensions = 256,
260 void setFeatures(long enabled) {m_features = enabled;}
261 bool isEnabled(components_t feature) {return (m_features & feature)>0;}
262 virtual IConfig* getINI() const {return m_ini;}
264 static const XMLCh SHIBTARGET_NS[];
265 static ShibTargetConfig& getConfig();
271 unsigned long m_features;
274 class SHIBTARGET_EXPORTS RM
277 RM(const IApplication* app) : m_app(app) {}
280 RPCError* getAssertions(
283 std::vector<saml::SAMLAssertion*>& assertions,
284 saml::SAMLAuthenticationStatement **statement = NULL
286 static void serialize(saml::SAMLAssertion &assertion, std::string &result);
289 const IApplication* m_app;
293 class SHIBTARGET_EXPORTS ShibMLP {
298 void insert (const std::string& key, const std::string& value);
299 void insert (const std::string& key, const char* value) {
300 std::string v = value;
303 void insert (const char* key, const std::string& value) {
307 void insert (const char* key, const char* value) {
308 std::string k = key, v = value;
311 void insert (RPCError& e);
313 void clear () { m_map.clear(); }
315 const char* run (std::istream& s, const IPropertySet* props=NULL, std::string* output=NULL);
316 const char* run (const std::string& input, const IPropertySet* props=NULL, std::string* output=NULL);
317 const char* run (const char* input, const IPropertySet* props=NULL, std::string* output=NULL) {
318 std::string i = input;
319 return run(i,props,output);
324 std::map<std::string,std::string> m_map;
325 std::string m_generated;
328 //******************************************************************************
330 // This is the interface you're looking for.
333 // This usurps the existing SHIRE and RM apis into a single class.
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, std::string &msg);
358 void log(ShibLogLevel level, const char *msg) {
363 // Get/Set a cookie for this connection
364 virtual std::string getCookies(void);
365 virtual void setCookie(std::string &name, std::string &value);
367 void setCookie(const char *name, const char *value) {
368 std::string ns = name;
369 std::string vs = value;
373 // Get the request's POST data from the server
374 virtual std::string getPostData(void);
376 // Not sure if I need these, but I might for something like Apache
377 // in order to "fix" the auth type in the case of basicHijack. In
378 // particular we need to maintain some state between the different
379 // APIs to know whether or not to proceed with shib processing.
380 virtual std::string getAuthType(void);
381 virtual void setAuthType(std::string);
383 void setAuthType(const char *type) {
384 std::string s = type;
388 virtual std::pair<bool,bool> getRequireSession(IRequestMapper::Settings &settings);
390 // Note: we still need to define exactly what kind of data in contained
391 // in the HTAccessInfo -- perhaps we can stub it out so non-htaccess
392 // systems have something they can plug in?
393 //virtual HTAccessInfo& getAccessInfo(void);
395 // We're done. Finish up. Send either a result (error?) page or a redirect.
396 virtual void* sendPage(
398 std::pair<std::string, std::string> headers[] = NULL,
401 virtual void* sendRedirect(std::string url);
403 // These next two APIs are used to obtain the module-specific "OK"
404 // and "Decline" results. OK means "we believe that this request
405 // should be accepted". Declined means "we believe that this is
406 // not a shibbolized request so we have no comment".
408 virtual void* returnDecline(void);
409 virtual void* returnOK(void);
412 // Note: Subclasses need not implement anything below this line
415 // These functions implement the server-agnostic shibboleth engine
416 // The web server modules implement a subclass and then call into
417 // these methods once they instantiate their request object.
420 // these APIs will always return the result of sendPage(), sendRedirect(),
421 // returnDecline(), or returnOK(). Exactly what those values are
422 // is module- (subclass-) implementation specific.
424 void* doCheckAuthN(void);
425 void* doHandlePOST(void);
426 void* doCheckAuthZ(void);
430 // Get the session cookie name and properties for the application
431 std::pair<const char*,const char*> getCookieNameProps() const;
433 // Find the default assertion consumer service for the resource
434 const char* getShireURL(const char* resource) const;
436 // Generate a Shib 1.x AuthnRequest redirect URL for the resource
437 const char* getAuthnRequest(const char* resource) const;
439 // Process a lazy session setup request and turn it into an AuthnRequest
440 const char* getLazyAuthnRequest(const char* query_string) const;
442 // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
443 std::pair<const char*,const char*>
444 getFormSubmission(const char* post, unsigned int len) const;
446 RPCError* sessionCreate(
447 const char* response,
451 RPCError* sessionIsValid(const char* session_id, const char* ip) const;
455 RPCError* getAssertions(
458 std::vector<saml::SAMLAssertion*>& assertions,
459 saml::SAMLAuthenticationStatement **statement = NULL
461 static void serialize(saml::SAMLAssertion &assertion, std::string &result);
467 // Initialize the request from the parsed URL
468 void init(ShibTargetConfig *config,
469 std::string protocol, std::string hostname, int port,
470 std::string uri, std::string content_type, std::string remote_host,
474 mutable ShibTargetPriv *m_priv;
477 //******************************************************************************
478 // You probably don't care about much below this line
479 // unless you are using the lower-layer APIs provided by
480 // the shib target library.
482 class SHIBTARGET_EXPORTS SHIRE
485 SHIRE(const IApplication* app) { m_st = new ShibTarget(app); }
486 ~SHIRE() { delete m_st; }
488 // Get the session cookie name and properties for the application
489 std::pair<const char*,const char*> getCookieNameProps() const
490 { return m_st->getCookieNameProps(); }
492 // Find the default assertion consumer service for the resource
493 const char* getShireURL(const char* resource) const
494 { return m_st->getShireURL(resource); }
496 // Generate a Shib 1.x AuthnRequest redirect URL for the resource
497 const char* getAuthnRequest(const char* resource) const
498 { return m_st->getAuthnRequest(resource); }
500 // Process a lazy session setup request and turn it into an AuthnRequest
501 const char* getLazyAuthnRequest(const char* query_string) const
502 { return m_st->getLazyAuthnRequest(query_string); }
504 // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
505 std::pair<const char*,const char*> getFormSubmission(const char* post, unsigned int len) const
506 { return m_st->getFormSubmission(post, len); }
508 RPCError* sessionCreate(const char* response, const char* ip, std::string &cookie) const
509 { return m_st->sessionCreate(response, ip, cookie); }
510 RPCError* sessionIsValid(const char* session_id, const char* ip) const
511 { return m_st->sessionIsValid(session_id, ip); }
515 //const IApplication* m_app;
516 //mutable std::string m_cookieName;
517 //mutable std::string m_shireURL;
518 //mutable std::string m_authnRequest;
519 //mutable CgiParse* m_parser;
524 #endif /* SHIB_TARGET_H */