Migrated Handler interface, set up segregated handler plugin factories.
authorScott Cantor <cantor.2@osu.edu>
Mon, 15 Jan 2007 07:33:27 +0000 (07:33 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 15 Jan 2007 07:33:27 +0000 (07:33 +0000)
15 files changed:
shib-target/shib-config.cpp
shib-target/shib-handlers.cpp
shib-target/shib-ini.cpp
shib-target/shib-target.cpp
shib-target/shib-target.h
shibsp/AbstractHandler.cpp [new file with mode: 0644]
shibsp/AbstractHandler.h [new file with mode: 0644]
shibsp/Handler.h [new file with mode: 0644]
shibsp/Makefile.am
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/shibsp.vcproj
shibsp/util/DOMPropertySet.h
shibsp/util/SPConstants.cpp
shibsp/util/SPConstants.h

index 09363f8..e0d23ad 100644 (file)
@@ -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<Handler,const DOMElement*>::Factory ShibSessionInitiatorFactory;
+PluginManager<Handler,const DOMElement*>::Factory SAML1POSTFactory;
+PluginManager<Handler,const DOMElement*>::Factory SAML1ArtifactFactory;
+PluginManager<Handler,const DOMElement*>::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;
index 890c544..608625e 100644 (file)
@@ -29,6 +29,7 @@
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/EndpointManager.h>
 #include <saml/util/CommonDomainCookie.h>
+#include <shibsp/AbstractHandler.h>
 #include <shibsp/SPConfig.h>
 
 #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<bool,long> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
     pair<bool,long> 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<bool,long> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> 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<bool,long> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> 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<bool,long> SessionInitiator::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
 {
     string dupresource;
     const char* resource=NULL;
-    const IHandler* ACS=NULL;
-    const IApplication& app=dynamic_cast<const IApplication&>(st->getApplication());
+    const Handler* ACS=NULL;
+    const IApplication& app=dynamic_cast<const IApplication&>(request.getApplication());
     
     if (isHandler) {
         /* 
@@ -120,12 +129,12 @@ pair<bool,long> 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<bool,const char*> home=app.getString("homeURL");
             if (home.first)
@@ -162,47 +171,47 @@ pair<bool,long> 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<bool,const char*> wayfURL=getProperties()->getString("wayfURL");
+    pair<bool,const char*> wayfURL=getString("wayfURL");
     if (!wayfURL.first)
         throw ConfigurationException("Session initiator is missing wayfURL property.");
 
-    pair<bool,const XMLCh*> wayfBinding=getProperties()->getXMLString("wayfBinding");
+    pair<bool,const XMLCh*> 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<bool,bool> localRelayState=st->getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState");
+        pair<bool,bool> 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<string,const char*> 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<bool,long> 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<bool,long> 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<bool,const char*> loc=shire ? shire->getProperties()->getString("Location") : pair<bool,const char*>(false,NULL);
+    string ACSloc=request.getHandlerURL(target);
+    pair<bool,const char*> loc=shire ? shire->getString("Location") : pair<bool,const char*>(false,NULL);
     if (loc.first) ACSloc+=loc.second;
     
     URLEncoder* urlenc = opensaml::SAMLConfig::getConfig().getURLEncoder();
@@ -221,7 +230,7 @@ pair<bool,long> SessionInitiator::ShibAuthnRequest(
     string req=string(dest) + "?shire=" + urlenc->encode(ACSloc.c_str()) + "&time=" + timebuf;
 
     // How should the resource value be preserved?
-    pair<bool,bool> localRelayState=st->getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState");
+    pair<bool,bool> 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<bool,long> 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<string,const char*> shib_cookie=st->getApplication().getCookieNameProps("_shibstate_");
+        pair<string,const char*> 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<bool,long> 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<bool,unsigned int> version=getProperties()->getUnsignedInt("MinorVersion","urn:oasis:names:tc:SAML:1.0:protocol");
+    pair<bool,unsigned int> 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<bool,long> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> SAML1Consumer::run(SPRequest& request, bool isHandler) const
 {
     DDF in,out;
     DDFJanitor jin(in),jout(out);
 
-    pair<bool,const XMLCh*> binding=getProperties()->getXMLString("Binding");
+    pair<bool,const XMLCh*> 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<bool,long>(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<bool,long>(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<bool,long>(false,0);
         }
 
@@ -476,17 +485,17 @@ pair<bool,long> 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<bool,long>(false,0);
         }
 
         vector<const char*> 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<bool,long>(false,0);
         }
 
@@ -498,34 +507,34 @@ pair<bool,long> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
     }
     
     // Compute the endpoint location.
-    string hURL=st->getHandlerURL(st->getRequestURL());
-    pair<bool,const char*> loc=getProperties()->getString("Location");
+    string hURL=request.getHandlerURL(request.getRequestURL());
+    pair<bool,const char*> 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<bool,const char*> homeURL=st->getApplication().getString("homeURL");
+        pair<bool,const char*> 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<string,const char*> relay_cookie = st->getApplication().getCookieNameProps("_shibstate_");
-        const char* relay_state = st->getCookie(relay_cookie.first.c_str());
+        pair<string,const char*> 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<bool,const char*> homeURL=st->getApplication().getString("homeURL");
+            pair<bool,const char*> homeURL=request.getApplication().getString("homeURL");
             target=homeURL.first ? homeURL.second : "/";
         }
         else {
@@ -535,27 +544,27 @@ pair<bool,long> 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<string,const char*> shib_cookie=st->getApplication().getCookieNameProps("_shibsession_");
+    pair<string,const char*> 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<bool,bool> 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<bool,unsigned int> 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<bool,long> 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<bool,long> ShibLogout::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> ShibLogout::run(SPRequest& request, bool isHandler) const
 {
     // Recover the session key.
-    pair<string,const char*> shib_cookie = st->getApplication().getCookieNameProps("_shibsession_");
-    const char* session_id = st->getCookie(shib_cookie.first.c_str());
+    pair<string,const char*> 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));
 }
index 5d76761..b09d090 100644 (file)
@@ -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<const IHandler*> 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<const Handler*> 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<IHandler*> m_handlers;
-        vector<PropertySet*> m_handlerProps;
+        // manage handler objects
+        vector<Handler*> m_handlers;
 
         // maps location (path info) to applicable handlers
-        map<string,const IHandler*> m_handlerMap;
+        map<string,const Handler*> m_handlerMap;
 
         // maps unique indexes to consumer services
-        map<unsigned int,const IHandler*> m_acsIndexMap;
+        map<unsigned int,const Handler*> 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<xmltooling::xstring,vector<const IHandler*> > ACSBindingMap;
+        typedef map<xmltooling::xstring,vector<const Handler*> > ACSBindingMap;
 #else
-        typedef map<string,vector<const IHandler*> > ACSBindingMap;
+        typedef map<string,vector<const Handler*> > ACSBindingMap;
 #endif
         ACSBindingMap m_acsBindingMap;
 
         // maps unique ID strings to session initiators
-        map<string,const IHandler*> m_sessionInitMap;
+        map<string,const Handler*> 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<string,IApplication*> m_appmap;
+        map<string,Application*> m_appmap;
         map<string,CredentialResolver*> m_credResolverMap;
         vector<IAttributeFactory*> 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<string,IApplication*>::const_iterator i=m_impl->m_appmap.find(applicationId);
+        const Application* getApplication(const char* applicationId) const {
+            map<string,Application*>::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<IHandler*>(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<const IHandler*>(1,hobj);
-                else
-                    m_acsBindingMap[binding].push_back(hobj);
-                m_acsIndexMap[hprops->getUnsignedInt("index").second]=hobj;
-                
-                if (!hardACS) {
-                    pair<bool,bool> 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<bool,bool> 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<bool,const char*> si_id=hprops->getString("id");
-                if (si_id.first && si_id.second)
-                    m_sessionInitMap[si_id.second]=hobj;
-                if (!hardSessionInit) {
-                    pair<bool,bool> 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<bool,const char*> si_id=handler->getString("id");
+                    if (si_id.first && si_id.second)
+                        m_sessionInitMap[si_id.second]=handler;
+                    if (!hardSessionInit) {
+                        pair<bool,bool> 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<bool,const char*> 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<IHandler*>(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<IHandler*>(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<IAAP*>(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<IHandler>());
+    for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
     
     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<string,const IHandler*>::const_iterator i=m_sessionInitMap.find(id);
+    map<string,const Handler*>::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<unsigned int,const IHandler*>::const_iterator i=m_acsIndexMap.find(index);
+    map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
     if (i!=m_acsIndexMap.end()) return i->second;
     return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;
 }
 
-Iterator<const IHandler*> XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
+Iterator<const Handler*> XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
 {
 #ifdef HAVE_GOOD_STL
     ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
@@ -841,13 +811,13 @@ Iterator<const IHandler*> 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<string,const IHandler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
+    map<string,const Handler*>::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<string,IApplication>());
+    for_each(m_appmap.begin(),m_appmap.end(),xmltooling::cleanup_pair<string,Application>());
     ShibConfig::getConfig().clearAttributeMappings();
     for_each(m_attrFactories.begin(),m_attrFactories.end(),xmltooling::cleanup<IAttributeFactory>());
     for_each(m_credResolverMap.begin(),m_credResolverMap.end(),xmltooling::cleanup_pair<string,CredentialResolver>());
index 74ad057..10e86b4 100644 (file)
@@ -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<bool,long> 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<bool,long> 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<bool,long> 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<bool,long> 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<bool,long> 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<bool,long> hret=handler->run(this);
+            procState = "Protocol Handler Error";
+        pair<bool,long> hret=handler->run(*this);
 
         // Did the handler run successfully?
         if (hret.first)
index bc29bb3..76c5ca6 100644 (file)
@@ -28,6 +28,7 @@
 // New headers
 #include <shibsp/AbstractSPRequest.h>
 #include <shibsp/Application.h>
+#include <shibsp/Handler.h>
 #include <shibsp/RequestMapper.h>
 #include <shibsp/ServiceProvider.h>
 #include <shibsp/remoting/ListenerService.h>
@@ -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<bool,long> 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<const IHandler*> 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<const shibsp::Handler*> 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 (file)
index 0000000..4ab6666
--- /dev/null
@@ -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<string,string>* 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 (file)
index 0000000..2b39b57
--- /dev/null
@@ -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 <shibsp/Handler.h>
+#include <shibsp/util/DOMPropertySet.h>
+
+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<std::string,std::string>* 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 (file)
index 0000000..a4d04ec
--- /dev/null
@@ -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 <shibsp/util/PropertySet.h>
+
+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.
+         * 
+         * <p>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<bool,long> run(SPRequest& request, bool isHandler=true) const=0;
+    };
+};
+
+#endif /* __shibsp_handler_h__ */
index 4950a62..3ee1936 100644 (file)
@@ -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 \
index a2ebfb4..7e4e5cc 100644 (file)
@@ -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();
index 9e57b2b..47f5e70 100644 (file)
@@ -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<AccessControl,const xercesc::DOMElement*> AccessControlManager;
 
         /**
+         * Manages factories for Handler plugins that implement AssertionConsumerService functionality.
+         */
+        xmltooling::PluginManager<Handler,const xercesc::DOMElement*> AssertionConsumerServiceManager;
+
+        /**
+         * Manages factories for Handler plugins that implement customized functionality.
+         */
+        xmltooling::PluginManager<Handler,const xercesc::DOMElement*> HandlerManager;
+
+        /**
          * Manages factories for ListenerService plugins.
          */
         xmltooling::PluginManager<ListenerService,const xercesc::DOMElement*> ListenerServiceManager;
 
         /**
+         * Manages factories for Handler plugins that implement ManageNameIDService functionality.
+         */
+        xmltooling::PluginManager<Handler,const xercesc::DOMElement*> ManageNameIDServiceManager;
+
+        /**
          * Manages factories for RequestMapper plugins.
          */
         xmltooling::PluginManager<RequestMapper,const xercesc::DOMElement*> RequestMapperManager;
@@ -151,6 +167,16 @@ namespace shibsp {
          */
         xmltooling::PluginManager<ServiceProvider,const xercesc::DOMElement*> ServiceProviderManager;
 
+        /**
+         * Manages factories for Handler plugins that implement SessionInitiator functionality.
+         */
+        xmltooling::PluginManager<Handler,const xercesc::DOMElement*> SessionInitiatorManager;
+
+        /**
+         * Manages factories for Handler plugins that implement SingleLogoutService functionality.
+         */
+        xmltooling::PluginManager<Handler,const xercesc::DOMElement*> SingleLogoutServiceManager;
+
     protected:
         SPConfig() : m_serviceProvider(NULL) {}
         
index a567849..e0796c5 100644 (file)
                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
                        >\r
                        <File\r
+                               RelativePath=".\AbstractHandler.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\AbstractSPRequest.cpp"\r
                                >\r
                        </File>\r
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
                        >\r
                        <File\r
+                               RelativePath=".\AbstractHandler.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\AbstractSPRequest.h"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\Handler.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\internal.h"\r
                                >\r
                        </File>\r
index d46d288..ced66c8 100644 (file)
@@ -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<std::string,std::pair<char*,const XMLCh*> > m_map;
         std::map<std::string,DOMPropertySet*> m_nested;
     };
+
 };
 
 #endif /* __shibsp_dompropset_h__ */
index 7bee69d..3f05837 100644 (file)
@@ -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\r
 };\r
 \r
-const XMLCh shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = // urn:mace:shibboleth:sp:1.3:SessionInit\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chLatin_s, chLatin_p, chColon, chDigit_1, chPeriod, chDigit_3, chColon,\r
-  chLatin_S, chLatin_e, chLatin_s, chLatin_s, chLatin_i, chLatin_o, chLatin_n, chLatin_I, chLatin_n, chLatin_i, chLatin_t, chNull\r
-};\r
+const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";\r
 \r
-const XMLCh shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = // urn:mace:shibboleth:sp:1.3:Logout\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chLatin_s, chLatin_p, chColon, chDigit_1, chPeriod, chDigit_3, chColon,\r
-  chLatin_L, chLatin_o, chLatin_g, chLatin_o, chLatin_u, chLatin_t, chNull\r
-};\r
+const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";\r
index 4f178f8..553edb2 100644 (file)
@@ -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__ */