From 7078eab30ce47a290eb370cbbc8fc86dfb80372e Mon Sep 17 00:00:00 2001 From: cantor Date: Mon, 15 Jan 2007 07:33:27 +0000 Subject: [PATCH] Migrated Handler interface, set up segregated handler plugin factories. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2128 cb58f699-b61c-0410-a6fe-9272a202ed29 --- shib-target/shib-config.cpp | 25 +++-- shib-target/shib-handlers.cpp | 179 +++++++++++++++++---------------- shib-target/shib-ini.cpp | 226 ++++++++++++++++++------------------------ shib-target/shib-target.cpp | 23 ++--- shib-target/shib-target.h | 33 ++---- shibsp/AbstractHandler.cpp | 34 +++++++ shibsp/AbstractHandler.h | 65 ++++++++++++ shibsp/Handler.h | 57 +++++++++++ shibsp/Makefile.am | 3 + shibsp/SPConfig.cpp | 8 +- shibsp/SPConfig.h | 26 +++++ shibsp/shibsp.vcproj | 12 +++ shibsp/util/DOMPropertySet.h | 3 +- shibsp/util/SPConstants.cpp | 14 +-- shibsp/util/SPConstants.h | 4 +- 15 files changed, 431 insertions(+), 281 deletions(-) create mode 100644 shibsp/AbstractHandler.cpp create mode 100644 shibsp/AbstractHandler.h create mode 100644 shibsp/Handler.h diff --git a/shib-target/shib-config.cpp b/shib-target/shib-config.cpp index 09363f8..e0d23ad 100644 --- a/shib-target/shib-config.cpp +++ b/shib-target/shib-config.cpp @@ -50,11 +50,11 @@ PlugManager::Factory UnixListenerFactory; PlugManager::Factory TCPListenerFactory; //PlugManager::Factory MemoryListenerFactory; PlugManager::Factory MemoryCacheFactory; -PlugManager::Factory ShibSessionInitiatorFactory; -PlugManager::Factory SAML1POSTFactory; -PlugManager::Factory SAML1ArtifactFactory; -PlugManager::Factory ShibLogoutFactory; -//PlugManager::Factory htaccessFactory; + +PluginManager::Factory ShibSessionInitiatorFactory; +PluginManager::Factory SAML1POSTFactory; +PluginManager::Factory SAML1ArtifactFactory; +PluginManager::Factory ShibLogoutFactory; ShibTargetConfig& ShibTargetConfig::getConfig() { @@ -90,6 +90,7 @@ bool STConfig::init(const char* schemadir) return false; } + SPConfig& conf=SPConfig::getConfig(); if (!SPConfig::getConfig().init(NULL)) { log.fatal("Failed to initialize SP library"); shibConf.term(); @@ -98,16 +99,14 @@ bool STConfig::init(const char* schemadir) } // Register built-in plugin types. - SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); + conf.ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); - samlConf.getPlugMgr().regFactory(MEMORY_SESSIONCACHE,&MemoryCacheFactory); + conf.SessionInitiatorManager.registerFactory(shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI,&ShibSessionInitiatorFactory); + conf.AssertionConsumerServiceManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_POST,&SAML1POSTFactory); + conf.AssertionConsumerServiceManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT,&SAML1ArtifactFactory); + conf.SingleLogoutServiceManager.registerFactory(shibspconstants::SHIB1_LOGOUT_PROFILE_URI,&ShibLogoutFactory); - auto_ptr_char temp1(shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI); - samlConf.getPlugMgr().regFactory(temp1.get(),&ShibSessionInitiatorFactory); - samlConf.getPlugMgr().regFactory(samlconstants::SAML1_PROFILE_BROWSER_POST,&SAML1POSTFactory); - samlConf.getPlugMgr().regFactory(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT,&SAML1ArtifactFactory); - auto_ptr_char temp4(shibspconstants::SHIB1_LOGOUT_PROFILE_URI); - samlConf.getPlugMgr().regFactory(temp4.get(),&ShibLogoutFactory); + samlConf.getPlugMgr().regFactory(MEMORY_SESSIONCACHE,&MemoryCacheFactory); log.info("finished initializing"); return true; diff --git a/shib-target/shib-handlers.cpp b/shib-target/shib-handlers.cpp index 890c544..608625e 100644 --- a/shib-target/shib-handlers.cpp +++ b/shib-target/shib-handlers.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -46,28 +47,33 @@ using namespace std; using opensaml::CommonDomainCookie; using opensaml::URLEncoder; +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + namespace { - class SessionInitiator : virtual public IHandler + class SessionInitiator : public AbstractHandler { public: - SessionInitiator(const DOMElement* e) {} + SessionInitiator(const DOMElement* e) : AbstractHandler(e) {} ~SessionInitiator() {} - pair run(ShibTarget* st, bool isHandler=true) const; + pair run(SPRequest& request, bool isHandler=true) const; pair ShibAuthnRequest( - ShibTarget* st, - const IHandler* shire, + SPRequest& request, + const Handler* shire, const char* dest, const char* target, const char* providerId ) const; }; - class SAML1Consumer : virtual public IHandler, public virtual Remoted + class SAML1Consumer : public AbstractHandler, public virtual Remoted { public: SAML1Consumer(const DOMElement* e); ~SAML1Consumer(); - pair run(ShibTarget* st, bool isHandler=true) const; + pair run(SPRequest& request, bool isHandler=true) const; DDF receive(const DDF& in); private: string m_address; @@ -76,42 +82,45 @@ namespace { int SAML1Consumer::counter = 0; - class ShibLogout : virtual public IHandler + class ShibLogout : public AbstractHandler { public: - ShibLogout(const DOMElement* e) {} + ShibLogout(const DOMElement* e) : AbstractHandler(e) {} ~ShibLogout() {} - pair run(ShibTarget* st, bool isHandler=true) const; + pair run(SPRequest& request, bool isHandler=true) const; }; } +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif -IPlugIn* ShibSessionInitiatorFactory(const DOMElement* e) +Handler* ShibSessionInitiatorFactory(const DOMElement* const & e) { return new SessionInitiator(e); } -IPlugIn* SAML1POSTFactory(const DOMElement* e) +Handler* SAML1POSTFactory(const DOMElement* const & e) { return new SAML1Consumer(e); } -IPlugIn* SAML1ArtifactFactory(const DOMElement* e) +Handler* SAML1ArtifactFactory(const DOMElement* const & e) { return new SAML1Consumer(e); } -IPlugIn* ShibLogoutFactory(const DOMElement* e) +Handler* ShibLogoutFactory(const DOMElement* const & e) { return new ShibLogout(e); } -pair SessionInitiator::run(ShibTarget* st, bool isHandler) const +pair SessionInitiator::run(SPRequest& request, bool isHandler) const { string dupresource; const char* resource=NULL; - const IHandler* ACS=NULL; - const IApplication& app=dynamic_cast(st->getApplication()); + const Handler* ACS=NULL; + const IApplication& app=dynamic_cast(request.getApplication()); if (isHandler) { /* @@ -120,12 +129,12 @@ pair SessionInitiator::run(ShibTarget* st, bool isHandler) const * acsIndex optional index of an ACS to use on the way back in * providerId optional direct invocation of a specific IdP */ - const char* option=st->getParameter("acsIndex"); + const char* option=request.getParameter("acsIndex"); if (option) ACS=app.getAssertionConsumerServiceByIndex(atoi(option)); - option=st->getParameter("providerId"); + option=request.getParameter("providerId"); - resource=st->getParameter("target"); + resource=request.getParameter("target"); if (!resource || !*resource) { pair home=app.getString("homeURL"); if (home.first) @@ -162,47 +171,47 @@ pair SessionInitiator::run(ShibTarget* st, bool isHandler) const ); auto_ptr_char dest(ep->getLocation()); return ShibAuthnRequest( - st,ACS ? ACS : app.getDefaultAssertionConsumerService(),dest.get(),resource,app.getString("providerId").second + request,ACS ? ACS : app.getDefaultAssertionConsumerService(),dest.get(),resource,app.getString("providerId").second ); } } else { // We're running as a "virtual handler" from within the filter. // The target resource is the current one and everything else is defaulted. - resource=st->getRequestURL(); + resource=request.getRequestURL(); } if (!ACS) ACS=app.getDefaultAssertionConsumerService(); // For now, we only support external session initiation via a wayfURL - pair wayfURL=getProperties()->getString("wayfURL"); + pair wayfURL=getString("wayfURL"); if (!wayfURL.first) throw ConfigurationException("Session initiator is missing wayfURL property."); - pair wayfBinding=getProperties()->getXMLString("wayfBinding"); + pair wayfBinding=getXMLString("wayfBinding"); if (!wayfBinding.first || !XMLString::compareString(wayfBinding.second,shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI)) // Standard Shib 1.x - return ShibAuthnRequest(st,ACS,wayfURL.second,resource,app.getString("providerId").second); - else if (!strcmp(getProperties()->getString("wayfBinding").second,"urn:mace:shibboleth:1.0:profiles:EAuth")) { + return ShibAuthnRequest(request,ACS,wayfURL.second,resource,app.getString("providerId").second); + else if (!strcmp(getString("wayfBinding").second,"urn:mace:shibboleth:1.0:profiles:EAuth")) { // TODO: Finalize E-Auth profile URI - pair localRelayState=st->getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); + pair localRelayState=request.getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); if (!localRelayState.first || !localRelayState.second) throw ConfigurationException("E-Authn requests cannot include relay state, so localRelayState must be enabled."); // Here we store the state in a cookie. pair shib_cookie=app.getCookieNameProps("_shibstate_"); string stateval = opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.second; - st->setCookie(shib_cookie.first.c_str(),stateval.c_str()); - return make_pair(true, st->sendRedirect(wayfURL.second)); + request.setCookie(shib_cookie.first.c_str(),stateval.c_str()); + return make_pair(true, request.sendRedirect(wayfURL.second)); } - throw opensaml::BindingException("Unsupported WAYF binding ($1).", xmltooling::params(1,getProperties()->getString("wayfBinding").second)); + throw opensaml::BindingException("Unsupported WAYF binding ($1).", xmltooling::params(1,getString("wayfBinding").second)); } // Handles Shib 1.x AuthnRequest profile. pair SessionInitiator::ShibAuthnRequest( - ShibTarget* st, - const IHandler* shire, + SPRequest& request, + const Handler* shire, const char* dest, const char* target, const char* providerId @@ -210,8 +219,8 @@ pair SessionInitiator::ShibAuthnRequest( { // Compute the ACS URL. We add the ACS location to the base handlerURL. // Legacy configs will not have the Location property specified, so no suffix will be added. - string ACSloc=st->getHandlerURL(target); - pair loc=shire ? shire->getProperties()->getString("Location") : pair(false,NULL); + string ACSloc=request.getHandlerURL(target); + pair loc=shire ? shire->getString("Location") : pair(false,NULL); if (loc.first) ACSloc+=loc.second; URLEncoder* urlenc = opensaml::SAMLConfig::getConfig().getURLEncoder(); @@ -221,7 +230,7 @@ pair SessionInitiator::ShibAuthnRequest( string req=string(dest) + "?shire=" + urlenc->encode(ACSloc.c_str()) + "&time=" + timebuf; // How should the resource value be preserved? - pair localRelayState=st->getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); + pair localRelayState=request.getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); if (!localRelayState.first || !localRelayState.second) { // The old way, just send it along. req+="&target=" + urlenc->encode(target); @@ -229,9 +238,9 @@ pair SessionInitiator::ShibAuthnRequest( else { // Here we store the state in a cookie and send a fixed // value to the IdP so we can recognize it on the way back. - pair shib_cookie=st->getApplication().getCookieNameProps("_shibstate_"); + pair shib_cookie=request.getApplication().getCookieNameProps("_shibstate_"); string stateval = urlenc->encode(target) + shib_cookie.second; - st->setCookie(shib_cookie.first.c_str(),stateval.c_str()); + request.setCookie(shib_cookie.first.c_str(),stateval.c_str()); req+="&target=cookie"; } @@ -239,10 +248,10 @@ pair SessionInitiator::ShibAuthnRequest( if (providerId) req+="&providerId=" + urlenc->encode(providerId); - return make_pair(true, st->sendRedirect(req.c_str())); + return make_pair(true, request.sendRedirect(req.c_str())); } -SAML1Consumer::SAML1Consumer(const DOMElement* e) +SAML1Consumer::SAML1Consumer(const DOMElement* e) : AbstractHandler(e) { m_address += ('A' + (counter++)); m_address += "::SAML1Consumer::run"; @@ -320,7 +329,7 @@ DDF SAML1Consumer::receive(const DDF& in) } // Supports either version... - pair version=getProperties()->getUnsignedInt("MinorVersion","urn:oasis:names:tc:SAML:1.0:protocol"); + pair version=getUnsignedInt("MinorVersion","urn:oasis:names:tc:SAML:1.0:protocol"); if (!version.first) version.second=1; @@ -441,33 +450,33 @@ DDF SAML1Consumer::receive(const DDF& in) return out; } -pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const +pair SAML1Consumer::run(SPRequest& request, bool isHandler) const { DDF in,out; DDFJanitor jin(in),jout(out); - pair binding=getProperties()->getXMLString("Binding"); + pair binding=getXMLString("Binding"); if (!binding.first || !XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_POST)) { #ifdef HAVE_STRCASECMP - if (strcasecmp(st->getMethod(), "POST")) { + if (strcasecmp(request.getMethod(), "POST")) { #else - if (_stricmp(st->getMethod(), "POST")) { + if (_stricmp(request.getMethod(), "POST")) { #endif - st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring non-POST request"); + request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring non-POST request"); return pair(false,NULL); } #ifdef HAVE_STRCASECMP - if (strcasecmp(st->getContentType().c_str(),"application/x-www-form-urlencoded")) { + if (strcasecmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) { #else - if (_stricmp(st->getContentType().c_str(),"application/x-www-form-urlencoded")) { + if (_stricmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) { #endif - st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type."); + request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type."); return pair(false,0); } - const char* samlResponse = st->getParameter("SAMLResponse"); + const char* samlResponse = request.getParameter("SAMLResponse"); if (!samlResponse) { - st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter."); + request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter."); return pair(false,0); } @@ -476,17 +485,17 @@ pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const } else if (!XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_ARTIFACT)) { #ifdef HAVE_STRCASECMP - if (strcasecmp(st->getMethod(), "GET")) { + if (strcasecmp(request.getMethod(), "GET")) { #else - if (_stricmp(st->getMethod(), "GET")) { + if (_stricmp(request.getMethod(), "GET")) { #endif - st->log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request"); + request.log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request"); return pair(false,0); } vector arts; - if (st->getParameters("SAMLart",arts)==0) { - st->log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter."); + if (request.getParameters("SAMLart",arts)==0) { + request.log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter."); return pair(false,0); } @@ -498,34 +507,34 @@ pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const } // Compute the endpoint location. - string hURL=st->getHandlerURL(st->getRequestURL()); - pair loc=getProperties()->getString("Location"); + string hURL=request.getHandlerURL(request.getRequestURL()); + pair loc=getString("Location"); string recipient=loc.first ? hURL + loc.second : hURL; in.addmember("recipient").string(recipient.c_str()); // Add remaining parameters. - in.addmember("application_id").string(st->getApplication().getId()); - in.addmember("client_address").string(st->getRemoteAddr().c_str()); + in.addmember("application_id").string(request.getApplication().getId()); + in.addmember("client_address").string(request.getRemoteAddr().c_str()); - out=st->getServiceProvider().getListenerService()->send(in); + out=request.getServiceProvider().getListenerService()->send(in); if (!out["key"].isstring()) throw opensaml::FatalProfileException("Remote processing of SAML 1.x Browser profile did not return a usable session key."); string key=out["key"].string(); - st->log(SPRequest::SPDebug, string("profile processing succeeded, new session created (") + key + ")"); + request.log(SPRequest::SPDebug, string("profile processing succeeded, new session created (") + key + ")"); - const char* target=st->getParameter("TARGET"); + const char* target=request.getParameter("TARGET"); if (target && !strcmp(target,"default")) { - pair homeURL=st->getApplication().getString("homeURL"); + pair homeURL=request.getApplication().getString("homeURL"); target=homeURL.first ? homeURL.second : "/"; } else if (!target || !strcmp(target,"cookie")) { // Pull the target value from the "relay state" cookie. - pair relay_cookie = st->getApplication().getCookieNameProps("_shibstate_"); - const char* relay_state = st->getCookie(relay_cookie.first.c_str()); + pair relay_cookie = request.getApplication().getCookieNameProps("_shibstate_"); + const char* relay_state = request.getCookie(relay_cookie.first.c_str()); if (!relay_state || !*relay_state) { // No apparent relay state value to use, so fall back on the default. - pair homeURL=st->getApplication().getString("homeURL"); + pair homeURL=request.getApplication().getString("homeURL"); target=homeURL.first ? homeURL.second : "/"; } else { @@ -535,27 +544,27 @@ pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const free(rscopy); target=hURL.c_str(); } - st->setCookie(relay_cookie.first.c_str(),relay_cookie.second); + request.setCookie(relay_cookie.first.c_str(),relay_cookie.second); } // We've got a good session, set the session cookie. - pair shib_cookie=st->getApplication().getCookieNameProps("_shibsession_"); + pair shib_cookie=request.getApplication().getCookieNameProps("_shibsession_"); key += shib_cookie.second; - st->setCookie(shib_cookie.first.c_str(), key.c_str()); + request.setCookie(shib_cookie.first.c_str(), key.c_str()); const char* providerId=out["provider_id"].string(); if (providerId) { - const PropertySet* sessionProps=st->getApplication().getPropertySet("Sessions"); + const PropertySet* sessionProps=request.getApplication().getPropertySet("Sessions"); pair idpHistory=sessionProps->getBool("idpHistory"); if (!idpHistory.first || idpHistory.second) { // Set an IdP history cookie locally (essentially just a CDC). - CommonDomainCookie cdc(st->getCookie(CommonDomainCookie::CDCName)); + CommonDomainCookie cdc(request.getCookie(CommonDomainCookie::CDCName)); // Either leave in memory or set an expiration. pair days=sessionProps->getUnsignedInt("idpHistoryDays"); if (!days.first || days.second==0) { key = string(cdc.set(providerId)) + shib_cookie.second; - st->setCookie(CommonDomainCookie::CDCName, key.c_str()); + request.setCookie(CommonDomainCookie::CDCName, key.c_str()); } else { time_t now=time(NULL) + (days.second * 24 * 60 * 60); @@ -568,45 +577,45 @@ pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const char timebuf[64]; strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime); key = string(cdc.set(providerId)) + shib_cookie.second + "; expires=" + timebuf; - st->setCookie(CommonDomainCookie::CDCName, key.c_str()); + request.setCookie(CommonDomainCookie::CDCName, key.c_str()); } } } // Now redirect to the target. - return make_pair(true, st->sendRedirect(target)); + return make_pair(true, request.sendRedirect(target)); } -pair ShibLogout::run(ShibTarget* st, bool isHandler) const +pair ShibLogout::run(SPRequest& request, bool isHandler) const { // Recover the session key. - pair shib_cookie = st->getApplication().getCookieNameProps("_shibsession_"); - const char* session_id = st->getCookie(shib_cookie.first.c_str()); + pair shib_cookie = request.getApplication().getCookieNameProps("_shibsession_"); + const char* session_id = request.getCookie(shib_cookie.first.c_str()); // Logout is best effort. if (session_id && *session_id) { try { // TODO: port to new cache API - //st->getServiceProvider().getSessionCache()->remove(session_id,st->getApplication(),st->getRemoteAddr().c_str()); + //request.getServiceProvider().getSessionCache()->remove(session_id,request.getApplication(),request.getRemoteAddr().c_str()); } catch (exception& e) { - st->log(SPRequest::SPError, string("logout processing failed with exception: ") + e.what()); + request.log(SPRequest::SPError, string("logout processing failed with exception: ") + e.what()); } #ifndef _DEBUG catch (...) { - st->log(SPRequest::SPError, "logout processing failed with unknown exception"); + request.log(SPRequest::SPError, "logout processing failed with unknown exception"); } #endif // We send the cookie property alone, which acts as an empty value. - st->setCookie(shib_cookie.first.c_str(),shib_cookie.second); + request.setCookie(shib_cookie.first.c_str(),shib_cookie.second); } - const char* ret=st->getParameter("return"); + const char* ret=request.getParameter("return"); if (!ret) - ret=getProperties()->getString("ResponseLocation").second; + ret=getString("ResponseLocation").second; if (!ret) - ret=st->getApplication().getString("homeURL").second; + ret=request.getApplication().getString("homeURL").second; if (!ret) ret="/"; - return make_pair(true, st->sendRedirect(ret)); + return make_pair(true, request.sendRedirect(ret)); } diff --git a/shib-target/shib-ini.cpp b/shib-target/shib-ini.cpp index 5d76761..b09d090 100644 --- a/shib-target/shib-ini.cpp +++ b/shib-target/shib-ini.cpp @@ -85,12 +85,12 @@ namespace { const RoleDescriptor* role=NULL, const TrustEngine* trust=NULL ) const; - const IHandler* getDefaultSessionInitiator() const; - const IHandler* getSessionInitiatorById(const char* id) const; - const IHandler* getDefaultAssertionConsumerService() const; - const IHandler* getAssertionConsumerServiceByIndex(unsigned short index) const; - Iterator getAssertionConsumerServicesByBinding(const XMLCh* binding) const; - const IHandler* getHandler(const char* path) const; + const Handler* getDefaultSessionInitiator() const; + const Handler* getSessionInitiatorById(const char* id) const; + const Handler* getDefaultAssertionConsumerService() const; + const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const; + Iterator getAssertionConsumerServicesByBinding(const XMLCh* binding) const; + const Handler* getHandler(const char* path) const; // Provides filter to exclude special config elements. short acceptNode(const DOMNode* node) const; @@ -109,32 +109,31 @@ namespace { SAMLBinding* m_binding; ShibHTTPHook* m_bindingHook; - // vectors manage object life for handlers and their property sets - vector m_handlers; - vector m_handlerProps; + // manage handler objects + vector m_handlers; // maps location (path info) to applicable handlers - map m_handlerMap; + map m_handlerMap; // maps unique indexes to consumer services - map m_acsIndexMap; + map m_acsIndexMap; // pointer to default consumer service - const IHandler* m_acsDefault; + const Handler* m_acsDefault; // maps binding strings to supporting consumer service(s) #ifdef HAVE_GOOD_STL - typedef map > ACSBindingMap; + typedef map > ACSBindingMap; #else - typedef map > ACSBindingMap; + typedef map > ACSBindingMap; #endif ACSBindingMap m_acsBindingMap; // maps unique ID strings to session initiators - map m_sessionInitMap; + map m_sessionInitMap; // pointer to default session initiator - const IHandler* m_sessionInitDefault; + const Handler* m_sessionInitDefault; DOMPropertySet* m_credDefault; #ifdef HAVE_GOOD_STL @@ -153,7 +152,7 @@ namespace { ~XMLConfigImpl(); RequestMapper* m_requestMapper; - map m_appmap; + map m_appmap; map m_credResolverMap; vector m_attrFactories; @@ -213,8 +212,8 @@ namespace { ISessionCache* getSessionCache() const {return m_sessionCache;} IReplayCache* getReplayCache() const {return m_replayCache;} RequestMapper* getRequestMapper() const {return m_impl->m_requestMapper;} - const IApplication* getApplication(const char* applicationId) const { - map::const_iterator i=m_impl->m_appmap.find(applicationId); + const Application* getApplication(const char* applicationId) const { + map::const_iterator i=m_impl->m_appmap.find(applicationId); return (i!=m_impl->m_appmap.end()) ? i->second : NULL; } @@ -318,98 +317,84 @@ XMLApplication::XMLApplication( m_hash+=getString("providerId").second; m_hash=samlConf.hashSHA1(m_hash.c_str(), true); - const DOMElement* child; - IPlugIn* plugin=NULL; - // Process handlers. + Handler* handler=NULL; bool hardACS=false, hardSessionInit=false; - child = XMLHelper::getFirstChildElement(propcheck->getElement()); + const DOMElement* child = XMLHelper::getFirstChildElement(propcheck->getElement()); while (child) { - // A handler is split across a property set and the plugin itself, which is based on the Binding property. - // We build both objects first and then insert them into various structures for lookup. - IHandler* hobj=NULL; - DOMPropertySet* hprops=new DOMPropertySet(); - try { - hprops->load(child,log,this); // filter irrelevant for now, no embedded elements expected - const char* bindprop=hprops->getString("Binding").second; - if (!bindprop) - throw ConfigurationException("Handler element has no Binding attribute, skipping it..."); - plugin=shibConf.getPlugMgr().newPlugin(bindprop,child); - hobj=dynamic_cast(plugin); - if (!hobj) { - delete plugin; - throw UnknownExtensionException( - "Plugin for binding ($1) does not implement IHandler interface.",xmltooling::params(1,bindprop) - ); - } - } - catch (exception& ex) { - // If we get here, the handler's not built, so dispose of the property set. - log.error("caught exception processing a handler element: %s",ex.what()); - delete hprops; - hprops=NULL; - } - - const char* location=hprops ? hprops->getString("Location").second : NULL; - if (!location) { - delete hprops; + xmltooling::auto_ptr_char bindprop(child->getAttributeNS(NULL,EndpointType::BINDING_ATTRIB_NAME)); + if (!bindprop.get() || !*(bindprop.get())) { + log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it..."); child = XMLHelper::getNextSiblingElement(child); continue; } - // Save off the objects after giving the property set to the handler for its use. - hobj->setProperties(hprops); - m_handlers.push_back(hobj); - m_handlerProps.push_back(hprops); - - // Insert into location map. - if (*location == '/') - m_handlerMap[location]=hobj; - else - m_handlerMap[string("/") + location]=hobj; - - // If it's an ACS or SI, handle index/id mappings and defaulting. - if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME)) { - // Map it. + try { + // A handler is based on the Binding property in conjunction with the element name. + // If it's an ACS or SI, also handle index/id mappings and defaulting. + if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME)) { + handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),child); + // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1) #ifdef HAVE_GOOD_STL - const XMLCh* binding=hprops->getXMLString("Binding").second; + m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler); #else - const char* binding=hprops->getString("Binding").second; + m_acsBindingMap[handler->getString("Binding").second].push_back(handler); #endif - if (m_acsBindingMap.count(binding)==0) - m_acsBindingMap[binding]=vector(1,hobj); - else - m_acsBindingMap[binding].push_back(hobj); - m_acsIndexMap[hprops->getUnsignedInt("index").second]=hobj; - - if (!hardACS) { - pair defprop=hprops->getBool("isDefault"); - if (defprop.first) { - if (defprop.second) { - hardACS=true; - m_acsDefault=hobj; + m_acsIndexMap[handler->getUnsignedInt("index").second]=handler; + + if (!hardACS) { + pair defprop=handler->getBool("isDefault"); + if (defprop.first) { + if (defprop.second) { + hardACS=true; + m_acsDefault=handler; + } } + else if (!m_acsDefault) + m_acsDefault=handler; } - else if (!m_acsDefault) - m_acsDefault=hobj; } - } - else if (XMLString::equals(child->getLocalName(),SessionInitiator)) { - pair si_id=hprops->getString("id"); - if (si_id.first && si_id.second) - m_sessionInitMap[si_id.second]=hobj; - if (!hardSessionInit) { - pair defprop=hprops->getBool("isDefault"); - if (defprop.first) { - if (defprop.second) { - hardSessionInit=true; - m_sessionInitDefault=hobj; + else if (XMLString::equals(child->getLocalName(),SessionInitiator)) { + handler=conf.SessionInitiatorManager.newPlugin(bindprop.get(),child); + pair si_id=handler->getString("id"); + if (si_id.first && si_id.second) + m_sessionInitMap[si_id.second]=handler; + if (!hardSessionInit) { + pair defprop=handler->getBool("isDefault"); + if (defprop.first) { + if (defprop.second) { + hardSessionInit=true; + m_sessionInitDefault=handler; + } } + else if (!m_sessionInitDefault) + m_sessionInitDefault=handler; } - else if (!m_sessionInitDefault) - m_sessionInitDefault=hobj; } + else if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME)) { + handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),child); + } + else if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,ManageNameIDService::LOCAL_NAME)) { + handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),child); + } + else { + handler=conf.HandlerManager.newPlugin(bindprop.get(),child); + } + } + catch (exception& ex) { + log.error("caught exception processing md:AssertionConsumerService element: %s",ex.what()); } + + // Save off the objects after giving the property set to the handler for its use. + m_handlers.push_back(handler); + + // Insert into location map. + pair location=handler->getString("Location"); + if (location.first && *location.second == '/') + m_handlerMap[location.second]=handler; + else if (location.first) + m_handlerMap[string("/") + location.second]=handler; + child = XMLHelper::getNextSiblingElement(child); } @@ -417,30 +402,15 @@ XMLApplication::XMLApplication( if (!m_base && m_handlers.empty()) { // A legacy config installs a SAML POST handler at the root handler location. // We use the Sessions element itself as the PropertySet. - - xmltooling::auto_ptr_char b1(shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI); - plugin=shibConf.getPlugMgr().newPlugin(b1.get(),propcheck->getElement()); - IHandler* h1=dynamic_cast(plugin); - if (!h1) { - delete plugin; - throw UnknownExtensionException( - "Plugin for binding ($1) does not implement IHandler interface.",xmltooling::params(1,b1.get()) - ); - } - h1->setProperties(propcheck); + Handler* h1=conf.SessionInitiatorManager.newPlugin( + shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI,propcheck->getElement() + ); m_handlers.push_back(h1); m_sessionInitDefault=h1; - xmltooling::auto_ptr_char b2(samlconstants::SAML1_PROFILE_BROWSER_POST); - plugin=shibConf.getPlugMgr().newPlugin(b2.get(),propcheck->getElement()); - IHandler* h2=dynamic_cast(plugin); - if (!h2) { - delete plugin; - throw UnknownExtensionException( - "Plugin for binding ($1) does not implement IHandler interface.",xmltooling::params(1,b2.get()) - ); - } - h2->setProperties(propcheck); + Handler* h2=conf.AssertionConsumerServiceManager.newPlugin( + samlconstants::SAML1_PROFILE_BROWSER_POST,propcheck->getElement() + ); m_handlers.push_back(h2); m_handlerMap[""] = h2; m_acsDefault=h2; @@ -467,7 +437,7 @@ XMLApplication::XMLApplication( xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); log.info("building AAP provider of type %s...",type.get()); try { - plugin=shibConf.getPlugMgr().newPlugin(type.get(),child); + IPlugIn* plugin=shibConf.getPlugMgr().newPlugin(type.get(),child); IAAP* aap=dynamic_cast(plugin); if (aap) m_aaps.push_back(aap); @@ -596,7 +566,7 @@ void XMLApplication::cleanup() delete m_bindingHook; delete m_binding; delete m_profile; - for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup()); + for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup()); delete m_credDefault; #ifdef HAVE_GOOD_STL @@ -805,33 +775,33 @@ void XMLApplication::validateToken(SAMLAssertion* token, time_t ts, const RoleDe throw xmltooling::XMLSecurityException("Assertion was unsigned, violating policy based on the issuer."); } -const IHandler* XMLApplication::getDefaultSessionInitiator() const +const Handler* XMLApplication::getDefaultSessionInitiator() const { if (m_sessionInitDefault) return m_sessionInitDefault; return m_base ? m_base->getDefaultSessionInitiator() : NULL; } -const IHandler* XMLApplication::getSessionInitiatorById(const char* id) const +const Handler* XMLApplication::getSessionInitiatorById(const char* id) const { - map::const_iterator i=m_sessionInitMap.find(id); + map::const_iterator i=m_sessionInitMap.find(id); if (i!=m_sessionInitMap.end()) return i->second; return m_base ? m_base->getSessionInitiatorById(id) : NULL; } -const IHandler* XMLApplication::getDefaultAssertionConsumerService() const +const Handler* XMLApplication::getDefaultAssertionConsumerService() const { if (m_acsDefault) return m_acsDefault; return m_base ? m_base->getDefaultAssertionConsumerService() : NULL; } -const IHandler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const +const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const { - map::const_iterator i=m_acsIndexMap.find(index); + map::const_iterator i=m_acsIndexMap.find(index); if (i!=m_acsIndexMap.end()) return i->second; return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL; } -Iterator XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const +Iterator XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const { #ifdef HAVE_GOOD_STL ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding); @@ -841,13 +811,13 @@ Iterator XMLApplication::getAssertionConsumerServicesByBinding( #endif if (i!=m_acsBindingMap.end()) return i->second; - return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : EMPTY(const IHandler*); + return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : EMPTY(const Handler*); } -const IHandler* XMLApplication::getHandler(const char* path) const +const Handler* XMLApplication::getHandler(const char* path) const { string wrap(path); - map::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?'))); + map::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?'))); if (i!=m_handlerMap.end()) return i->second; return m_base ? m_base->getHandler(path) : NULL; @@ -1160,7 +1130,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o XMLConfigImpl::~XMLConfigImpl() { - for_each(m_appmap.begin(),m_appmap.end(),xmltooling::cleanup_pair()); + for_each(m_appmap.begin(),m_appmap.end(),xmltooling::cleanup_pair()); ShibConfig::getConfig().clearAttributeMappings(); for_each(m_attrFactories.begin(),m_attrFactories.end(),xmltooling::cleanup()); for_each(m_credResolverMap.begin(),m_credResolverMap.end(),xmltooling::cleanup_pair()); diff --git a/shib-target/shib-target.cpp b/shib-target/shib-target.cpp index 74ad057..10e86b4 100644 --- a/shib-target/shib-target.cpp +++ b/shib-target/shib-target.cpp @@ -90,7 +90,6 @@ namespace shibtarget { long _sendError(SPRequest* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex=NULL); static const XMLCh SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r); - static const XMLCh DiagnosticService[] = UNICODE_LITERAL_17(D,i,a,g,n,o,s,t,i,c,S,e,r,v,i,c,e); } @@ -179,7 +178,7 @@ pair ShibTarget::doCheckAuthN(bool handler) // No cookie, but we require a session. Initiate a new session using the indicated method. procState = "Session Initiator Error"; - const IHandler* initiator=NULL; + const Handler* initiator=NULL; if (requireSessionWith.first) { initiator=app.getSessionInitiatorById(requireSessionWith.second); if (!initiator) @@ -194,7 +193,7 @@ pair ShibTarget::doCheckAuthN(bool handler) throw ConfigurationException("No default session initiator found, check configuration."); } - return initiator->run(this,false); + return initiator->run(*this,false); } procState = "Session Processing Error"; @@ -222,7 +221,7 @@ pair ShibTarget::doCheckAuthN(bool handler) if (trycast) { // Session is invalid but we can retry -- initiate a new session. procState = "Session Initiator Error"; - const IHandler* initiator=NULL; + const Handler* initiator=NULL; if (requireSessionWith.first) { initiator=app.getSessionInitiatorById(requireSessionWith.second); if (!initiator) @@ -236,7 +235,7 @@ pair ShibTarget::doCheckAuthN(bool handler) if (!initiator) throw ConfigurationException("No default session initiator found, check configuration."); } - return initiator->run(this,false); + return initiator->run(*this,false); } throw; // send it to the outer handler } @@ -298,21 +297,19 @@ pair ShibTarget::doHandler(void) // We dispatch based on our path info. We know the request URL begins with or equals the handler URL, // so the path info is the next character (or null). - const IHandler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL)); + const Handler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL)); if (!handler) throw opensaml::BindingException("Shibboleth handler invoked at an unconfigured location."); - if (XMLHelper::isNodeNamed(handler->getProperties()->getElement(),samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME)) + if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME)) procState = "Session Creation Error"; - else if (XMLString::equals(handler->getProperties()->getElement()->getLocalName(),SessionInitiator)) + else if (XMLString::equals(handler->getElement()->getLocalName(),SessionInitiator)) procState = "Session Initiator Error"; - else if (XMLHelper::isNodeNamed(handler->getProperties()->getElement(),samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME)) + else if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME)) procState = "Session Termination Error"; - else if (XMLString::equals(handler->getProperties()->getElement()->getLocalName(),DiagnosticService)) - procState = "Diagnostics Error"; else - procState = "Extension Service Error"; - pair hret=handler->run(this); + procState = "Protocol Handler Error"; + pair hret=handler->run(*this); // Did the handler run successfully? if (hret.first) diff --git a/shib-target/shib-target.h b/shib-target/shib-target.h index bc29bb3..76c5ca6 100644 --- a/shib-target/shib-target.h +++ b/shib-target/shib-target.h @@ -28,6 +28,7 @@ // New headers #include #include +#include #include #include #include @@ -51,26 +52,6 @@ namespace shibtarget { // Abstract APIs for access to configuration information - // Forward declaration - class SHIBTARGET_EXPORTS ShibTarget; - - /** - * Interface to a protocol handler - * - * Protocol handlers perform system functions such as processing SAML protocol - * messages to create and logout sessions or creating protocol requests. - */ - struct SHIBTARGET_EXPORTS IHandler : public virtual saml::IPlugIn - { - IHandler() : m_props(NULL) {} - virtual ~IHandler() {} - virtual const shibsp::PropertySet* getProperties() const { return m_props; } - virtual void setProperties(const shibsp::PropertySet* properties) { m_props=properties; } - virtual std::pair run(ShibTarget* st, bool isHandler=true) const=0; - private: - const shibsp::PropertySet* m_props; - }; - /** * Interface to Shibboleth Applications, which exposes most of the functionality * required to process web requests or security protocol messages for resources @@ -105,16 +86,16 @@ namespace shibtarget { ) const=0; // Used to locate a default or designated session initiator for automatic sessions - virtual const IHandler* getDefaultSessionInitiator() const=0; - virtual const IHandler* getSessionInitiatorById(const char* id) const=0; + virtual const shibsp::Handler* getDefaultSessionInitiator() const=0; + virtual const shibsp::Handler* getSessionInitiatorById(const char* id) const=0; // Used by session initiators to get endpoint to forward to IdP/WAYF - virtual const IHandler* getDefaultAssertionConsumerService() const=0; - virtual const IHandler* getAssertionConsumerServiceByIndex(unsigned short index) const=0; - virtual saml::Iterator getAssertionConsumerServicesByBinding(const XMLCh* binding) const=0; + virtual const shibsp::Handler* getDefaultAssertionConsumerService() const=0; + virtual const shibsp::Handler* getAssertionConsumerServiceByIndex(unsigned short index) const=0; + virtual saml::Iterator getAssertionConsumerServicesByBinding(const XMLCh* binding) const=0; // Used by dispatcher to locate the handler for a request - virtual const IHandler* getHandler(const char* path) const=0; + virtual const shibsp::Handler* getHandler(const char* path) const=0; virtual ~IApplication() {} }; diff --git a/shibsp/AbstractHandler.cpp b/shibsp/AbstractHandler.cpp new file mode 100644 index 0000000..4ab6666 --- /dev/null +++ b/shibsp/AbstractHandler.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * AbstractHandler.cpp + * + * Base class for handlers based on a DOMPropertySet. + */ + +#include "internal.h" +#include "AbstractHandler.h" + +using namespace shibsp; +using namespace xercesc; +using namespace std; + +AbstractHandler::AbstractHandler( + const DOMElement* e, DOMNodeFilter* filter, const map* remapper + ) { + load(e,log4cpp::Category::getInstance(SHIBSP_LOGCAT".AbstractHandler"),filter,remapper); +} diff --git a/shibsp/AbstractHandler.h b/shibsp/AbstractHandler.h new file mode 100644 index 0000000..2b39b57 --- /dev/null +++ b/shibsp/AbstractHandler.h @@ -0,0 +1,65 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file shibsp/AbstractHandler.h + * + * Base class for handlers based on a DOMPropertySet. + */ + +#ifndef __shibsp_abshandler_h__ +#define __shibsp_abshandler_h__ + +#include +#include + +namespace shibsp { + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + /** + * Base class for handlers based on a DOMPropertySet. + */ + class SHIBSP_API AbstractHandler : public virtual Handler, public DOMPropertySet + { + protected: + /** + * Constructor + * + * @param e DOM element to load as property set. + * @param filter optional filter controls what child elements to include as nested PropertySets + * @param remapper optional map of property rename rules for legacy property support + */ + AbstractHandler( + const xercesc::DOMElement* e, + xercesc::DOMNodeFilter* filter=NULL, + const std::map* remapper=NULL + ); + + public: + virtual ~AbstractHandler() {} + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +}; + +#endif /* __shibsp_abshandler_h__ */ diff --git a/shibsp/Handler.h b/shibsp/Handler.h new file mode 100644 index 0000000..a4d04ec --- /dev/null +++ b/shibsp/Handler.h @@ -0,0 +1,57 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file shibsp/Handler.h + * + * Pluggable runtime functionality that implement protocols and services + */ + +#ifndef __shibsp_handler_h__ +#define __shibsp_handler_h__ + +#include + +namespace shibsp { + + class SHIBSP_API SPRequest; + + /** + * Pluggable runtime functionality that implement protocols and services + */ + class SHIBSP_API Handler : public virtual PropertySet + { + MAKE_NONCOPYABLE(Handler); + protected: + Handler() {} + public: + virtual ~Handler() {} + + /** + * Executes handler functionality as an incoming request. + * + *

Handlers can be run either directly by incoming web requests + * or indirectly/implicitly during other SP processing. + * + * @param request SP request context + * @param isHandler true iff executing in the context of a direct handler invocation + * @return a pair containing a "request completed" indicator and a server-specific response code + */ + virtual std::pair run(SPRequest& request, bool isHandler=true) const=0; + }; +}; + +#endif /* __shibsp_handler_h__ */ diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am index 4950a62..3ee1936 100644 --- a/shibsp/Makefile.am +++ b/shibsp/Makefile.am @@ -16,11 +16,13 @@ secincludedir = $(includedir)/shibsp/security utilincludedir = $(includedir)/shibsp/util libshibspinclude_HEADERS = \ + AbstractHandler.h \ AbstractSPRequest.h \ AccessControl.h \ Application.h \ base.h \ exceptions.h \ + Handler.h \ paths.h \ RequestMapper.h \ ServiceProvider.h \ @@ -49,6 +51,7 @@ noinst_HEADERS = \ remoting/impl/SocketListener.h libshibsp_la_SOURCES = \ + AbstractHandler.cpp \ AbstractSPRequest.cpp \ Application.cpp \ ServiceProvider.cpp \ diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp index a2ebfb4..7e4e5cc 100644 --- a/shibsp/SPConfig.cpp +++ b/shibsp/SPConfig.cpp @@ -22,8 +22,9 @@ */ #include "internal.h" -#include "exceptions.h" #include "AccessControl.h" +#include "exceptions.h" +#include "Handler.h" #include "RequestMapper.h" #include "ServiceProvider.h" #include "SPConfig.h" @@ -116,9 +117,14 @@ void SPInternalConfig::term() delete m_serviceProvider; m_serviceProvider = NULL; + SingleLogoutServiceManager.deregisterFactories(); + SessionInitiatorManager.deregisterFactories(); ServiceProviderManager.deregisterFactories(); RequestMapperManager.deregisterFactories(); + ManageNameIDServiceManager.deregisterFactories(); ListenerServiceManager.deregisterFactories(); + HandlerManager.deregisterFactories(); + AssertionConsumerServiceManager.deregisterFactories(); AccessControlManager.deregisterFactories(); SAMLConfig::getConfig().term(); diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h index 9e57b2b..47f5e70 100644 --- a/shibsp/SPConfig.h +++ b/shibsp/SPConfig.h @@ -34,6 +34,7 @@ namespace shibsp { class SHIBSP_API AccessControl; + class SHIBSP_API Handler; class SHIBSP_API ListenerService; class SHIBSP_API RequestMapper; class SHIBSP_API ServiceProvider; @@ -137,11 +138,26 @@ namespace shibsp { xmltooling::PluginManager AccessControlManager; /** + * Manages factories for Handler plugins that implement AssertionConsumerService functionality. + */ + xmltooling::PluginManager AssertionConsumerServiceManager; + + /** + * Manages factories for Handler plugins that implement customized functionality. + */ + xmltooling::PluginManager HandlerManager; + + /** * Manages factories for ListenerService plugins. */ xmltooling::PluginManager ListenerServiceManager; /** + * Manages factories for Handler plugins that implement ManageNameIDService functionality. + */ + xmltooling::PluginManager ManageNameIDServiceManager; + + /** * Manages factories for RequestMapper plugins. */ xmltooling::PluginManager RequestMapperManager; @@ -151,6 +167,16 @@ namespace shibsp { */ xmltooling::PluginManager ServiceProviderManager; + /** + * Manages factories for Handler plugins that implement SessionInitiator functionality. + */ + xmltooling::PluginManager SessionInitiatorManager; + + /** + * Manages factories for Handler plugins that implement SingleLogoutService functionality. + */ + xmltooling::PluginManager SingleLogoutServiceManager; + protected: SPConfig() : m_serviceProvider(NULL) {} diff --git a/shibsp/shibsp.vcproj b/shibsp/shibsp.vcproj index a567849..e0796c5 100644 --- a/shibsp/shibsp.vcproj +++ b/shibsp/shibsp.vcproj @@ -185,6 +185,10 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -283,6 +287,10 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -303,6 +311,10 @@ > + + diff --git a/shibsp/util/DOMPropertySet.h b/shibsp/util/DOMPropertySet.h index d46d288..ced66c8 100644 --- a/shibsp/util/DOMPropertySet.h +++ b/shibsp/util/DOMPropertySet.h @@ -34,7 +34,7 @@ namespace shibsp { class SHIBSP_API DOMPropertySet : public virtual PropertySet { public: - DOMPropertySet() {} + DOMPropertySet() : m_root(NULL) {} virtual ~DOMPropertySet(); @@ -69,6 +69,7 @@ namespace shibsp { std::map > m_map; std::map m_nested; }; + }; #endif /* __shibsp_dompropset_h__ */ diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp index 7bee69d..3f05837 100644 --- a/shibsp/util/SPConstants.cpp +++ b/shibsp/util/SPConstants.cpp @@ -82,16 +82,6 @@ const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shib chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull }; -const XMLCh shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = // urn:mace:shibboleth:sp:1.3:SessionInit -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chLatin_s, chLatin_p, chColon, chDigit_1, chPeriod, chDigit_3, chColon, - chLatin_S, chLatin_e, chLatin_s, chLatin_s, chLatin_i, chLatin_o, chLatin_n, chLatin_I, chLatin_n, chLatin_i, chLatin_t, chNull -}; +const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit"; -const XMLCh shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = // urn:mace:shibboleth:sp:1.3:Logout -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chLatin_s, chLatin_p, chColon, chDigit_1, chPeriod, chDigit_3, chColon, - chLatin_L, chLatin_o, chLatin_g, chLatin_o, chLatin_u, chLatin_t, chNull -}; +const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout"; diff --git a/shibsp/util/SPConstants.h b/shibsp/util/SPConstants.h index 4f178f8..553edb2 100644 --- a/shibsp/util/SPConstants.h +++ b/shibsp/util/SPConstants.h @@ -56,10 +56,10 @@ namespace shibspconstants { extern SHIBSP_API const XMLCh SHIB1_AUTHNREQUEST_PROFILE_URI[]; /** Shibboleth 1.3 SessionInit binding/profile ("urn:mace:shibboleth:sp:1.3:SessionInit") */ - extern SHIBSP_API const XMLCh SHIB1_SESSIONINIT_PROFILE_URI[]; + extern SHIBSP_API const char SHIB1_SESSIONINIT_PROFILE_URI[]; /** Shibboleth 1.3 Local Logout binding/profile ("urn:mace:shibboleth:sp:1.3:Logout") */ - extern SHIBSP_API const XMLCh SHIB1_LOGOUT_PROFILE_URI[]; + extern SHIBSP_API const char SHIB1_LOGOUT_PROFILE_URI[]; }; #endif /* __shibsp_constants_h__ */ -- 2.1.4