Need to use SP-specific policy subclass for SOAP client.
[shibboleth/sp.git] / shib-target / shib-handlers.cpp
index 313b0b5..8c2583b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2005 Internet2
+ *  Copyright 2001-2007 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,8 +29,9 @@
 #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>
-#include <shibsp/SPConstants.h>
+#include <shibsp/SPRequest.h>
 
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
@@ -47,29 +48,34 @@ 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,void*> run(ShibTarget* st, bool isHandler=true) const;
-    pair<bool,void*> ShibAuthnRequest(
-        ShibTarget* st,
-        const IHandler* shire,
+    pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
+    pair<bool,long> ShibAuthnRequest(
+        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,void*> run(ShibTarget* st, bool isHandler=true) const;
-    DDF receive(const DDF& in);
+    pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
+    void receive(DDF& in, ostream& out);
   private:
     string m_address;
     static int counter;
@@ -77,42 +83,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,void*> 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,void*> 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=st->getApplication();
+    const Handler* ACS=NULL;
+    const IApplication& app=dynamic_cast<const IApplication&>(request.getApplication());
     
     if (isHandler) {
         /* 
@@ -121,14 +130,14 @@ pair<bool,void*> 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->getRequestParameter("acsIndex");
+        const char* option=request.getParameter("acsIndex");
         if (option)
-            ACS=app->getAssertionConsumerServiceByIndex(atoi(option));
-        option=st->getRequestParameter("providerId");
+            ACS=app.getAssertionConsumerServiceByIndex(atoi(option));
+        option=request.getParameter("providerId");
         
-        resource=st->getRequestParameter("target");
+        resource=request.getParameter("target");
         if (!resource || !*resource) {
-            pair<bool,const char*> home=app->getString("homeURL");
+            pair<bool,const char*> home=app.getString("homeURL");
             if (home.first)
                 resource=home.second;
             else
@@ -143,7 +152,7 @@ pair<bool,void*> SessionInitiator::run(ShibTarget* st, bool isHandler) const
             // Here we actually use metadata to invoke the SSO service directly.
             // The only currently understood binding is the Shibboleth profile.
             
-            MetadataProvider* m=app->getMetadataProvider();
+            MetadataProvider* m=app.getMetadataProvider();
             xmltooling::Locker locker(m);
             const EntityDescriptor* entity=m->getEntityDescriptor(option);
             if (!entity)
@@ -163,46 +172,47 @@ pair<bool,void*> 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();
+    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->getConfig()->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=st->getCookieNameProps("_shibstate_");
-        st->setCookie(shib_cookie.first,opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.second);
-        return make_pair(true, st->sendRedirect(wayfURL.second));
+        pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibstate_");
+        string stateval = opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.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,void*> SessionInitiator::ShibAuthnRequest(
-    ShibTarget* st,
-    const IHandler* shire,
+pair<bool,long> SessionInitiator::ShibAuthnRequest(
+    SPRequest& request,
+    const Handler* shire,
     const char* dest,
     const char* target,
     const char* providerId
@@ -210,8 +220,8 @@ pair<bool,void*> 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 +231,7 @@ pair<bool,void*> 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->getConfig()->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,8 +239,9 @@ pair<bool,void*> 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->getCookieNameProps("_shibstate_");
-        st->setCookie(shib_cookie.first,urlenc->encode(target) + shib_cookie.second);
+        pair<string,const char*> shib_cookie=request.getApplication().getCookieNameProps("_shibstate_");
+        string stateval = urlenc->encode(target) + shib_cookie.second;
+        request.setCookie(shib_cookie.first.c_str(),stateval.c_str());
         req+="&target=cookie";
     }
     
@@ -238,22 +249,22 @@ pair<bool,void*> SessionInitiator::ShibAuthnRequest(
     if (providerId)
         req+="&providerId=" + urlenc->encode(providerId);
 
-    return make_pair(true, st->sendRedirect(req));
+    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";
 
     // Register for remoted messages.
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
-        ShibTargetConfig::getConfig().getINI()->getListenerService()->regListener(m_address.c_str(),this);
+        SPConfig::getConfig().getServiceProvider()->getListenerService()->regListener(m_address.c_str(),this);
 }
 
 SAML1Consumer::~SAML1Consumer()
 {
-    ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListenerService(false);
+    ListenerService* listener=SPConfig::getConfig().getServiceProvider()->getListenerService(false);
     if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
         listener->unregListener(m_address.c_str(),this);
     counter--;
@@ -274,7 +285,7 @@ SAML1Consumer::~SAML1Consumer()
  *      key
  *      provider_id
  */
-DDF SAML1Consumer::receive(const DDF& in)
+void SAML1Consumer::receive(DDF& in, ostream& sink)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("receive");
@@ -283,7 +294,7 @@ DDF SAML1Consumer::receive(const DDF& in)
 
     // Find application.
     const char* aid=in["application_id"].string();
-    const IApplication* app=aid ? ShibTargetConfig::getConfig().getINI()->getApplication(aid) : NULL;
+    const IApplication* app=aid ? dynamic_cast<const IApplication*>(SPConfig::getConfig().getServiceProvider()->getApplication(aid)) : NULL;
     if (!app) {
         // Something's horribly wrong.
         log.error("couldn't find application (%s) for new session", aid ? aid : "(missing)");
@@ -301,8 +312,7 @@ DDF SAML1Consumer::receive(const DDF& in)
     log.debug("application: %s", app->getId());
 
     // Access the application config.
-    STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
-    IConfig* conf=stc.getINI();
+    ServiceProvider* conf=SPConfig::getConfig().getServiceProvider();
     xmltooling::Locker confLocker(conf);
 
     auto_ptr_XMLCh wrecipient(recipient);
@@ -320,7 +330,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;
 
@@ -338,7 +348,7 @@ DDF SAML1Consumer::receive(const DDF& in)
             bpr=app->getBrowserProfile()->receive(
                 samlResponse,
                 wrecipient.get(),
-                checkReplay.second ? conf->getReplayCache() : NULL,
+                NULL,
                 version.second
                 );
         }
@@ -357,7 +367,7 @@ DDF SAML1Consumer::receive(const DDF& in)
                 SAMLart,
                 wrecipient.get(),
                 artifactMapper.get(),
-                checkReplay.second ? conf->getReplayCache() : NULL,
+                NULL,
                 version.second
                 );
 
@@ -423,7 +433,7 @@ DDF SAML1Consumer::receive(const DDF& in)
 
     // Insert into cache.
     auto_ptr_char authContext(bpr.authnStatement->getAuthMethod());
-    string key=conf->getSessionCache()->insert(
+    string key=dynamic_cast<ISessionCache*>(conf->getSessionCache())->insert(
         app,
         role,
         client_address,
@@ -438,37 +448,37 @@ DDF SAML1Consumer::receive(const DDF& in)
     out.addmember("key").string(key.c_str());
     out.addmember("provider_id").string(oname.get());
 
-    return out;
+    sink << out;
 }
 
-pair<bool,void*> 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->getRequestMethod(), "POST")) {
+        if (strcasecmp(request.getMethod(), "POST")) {
 #else
-        if (_stricmp(st->getRequestMethod(), "POST")) {
+        if (_stricmp(request.getMethod(), "POST")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring non-POST request");
-            return pair<bool,void*>(false,NULL);
+            request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring non-POST request");
+            return pair<bool,long>(false,NULL);
         }
 #ifdef HAVE_STRCASECMP
-        if (!st->getContentType() || strcasecmp(st->getContentType(),"application/x-www-form-urlencoded")) {
+        if (strcasecmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) {
 #else
-        if (!st->getContentType() || _stricmp(st->getContentType(),"application/x-www-form-urlencoded")) {
+        if (_stricmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type.");
-            return pair<bool,void*>(false,NULL);
+            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->getRequestParameter("SAMLResponse");
+        const char* samlResponse = request.getParameter("SAMLResponse");
         if (!samlResponse) {
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter.");
-            return pair<bool,void*>(false,NULL);
+            request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter.");
+            return pair<bool,long>(false,0);
         }
 
         in=DDF(m_address.c_str()).structure();
@@ -476,58 +486,56 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
     }
     else if (!XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_ARTIFACT)) {
 #ifdef HAVE_STRCASECMP
-        if (strcasecmp(st->getRequestMethod(), "GET")) {
+        if (strcasecmp(request.getMethod(), "GET")) {
 #else
-        if (_stricmp(st->getRequestMethod(), "GET")) {
+        if (_stricmp(request.getMethod(), "GET")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request");
-            return pair<bool,void*>(false,NULL);
+            request.log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request");
+            return pair<bool,long>(false,0);
         }
 
-        const char* SAMLart=st->getRequestParameter("SAMLart");
-        if (!SAMLart) {
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter.");
-            return pair<bool,void*>(false,NULL);
+        vector<const char*> arts;
+        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);
         }
 
         in=DDF(m_address.c_str()).structure();
         DDF artlist=in.addmember("SAMLart").list();
 
-        while (SAMLart) {
-            artlist.add(DDF(NULL).string(SAMLart));
-            SAMLart=st->getRequestParameter("SAMLart",artlist.integer());
-        }
+        for (vector<const char*>::const_iterator a=arts.begin(); a!=arts.end(); ++a)
+            artlist.add(DDF(NULL).string(*a));
     }
     
     // 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());
+    in.addmember("application_id").string(request.getApplication().getId());
+    in.addmember("client_address").string(request.getRemoteAddr().c_str());
 
-    out=st->getConfig()->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(ShibTarget::LogLevelDebug, string("profile processing succeeded, new session created (") + key + ")");
+    request.log(SPRequest::SPDebug, string("profile processing succeeded, new session created (") + key + ")");
 
-    const char* target=st->getRequestParameter("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->getCookieNameProps("_shibstate_");
-        const char* relay_state = st->getCookie(relay_cookie.first);
+        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 {
@@ -537,76 +545,78 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
             free(rscopy);
             target=hURL.c_str();
         }
-        st->setCookie(relay_cookie.first,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->getCookieNameProps("_shibsession_");
-    st->setCookie(shib_cookie.first, key + shib_cookie.second);
+    pair<string,const char*> shib_cookie=request.getApplication().getCookieNameProps("_shibsession_");
+    key += shib_cookie.second;
+    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)
-                    st->setCookie(CommonDomainCookie::CDCName,string(cdc.set(providerId)) + shib_cookie.second);
-                else {
-                    time_t now=time(NULL) + (days.second * 24 * 60 * 60);
+            if (!days.first || days.second==0) {
+                key = string(cdc.set(providerId)) + shib_cookie.second;
+                request.setCookie(CommonDomainCookie::CDCName, key.c_str());
+            }
+            else {
+                time_t now=time(NULL) + (days.second * 24 * 60 * 60);
 #ifdef HAVE_GMTIME_R
-                    struct tm res;
-                    struct tm* ptime=gmtime_r(&now,&res);
+                struct tm res;
+                struct tm* ptime=gmtime_r(&now,&res);
 #else
-                    struct tm* ptime=gmtime(&now);
+                struct tm* ptime=gmtime(&now);
 #endif
-                    char timebuf[64];
-                    strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime);
-                    st->setCookie(
-                        CommonDomainCookie::CDCName,
-                        string(cdc.set(providerId)) + shib_cookie.second + "; expires=" + timebuf
-                        );
+                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;
+                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,void*> 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->getCookieNameProps("_shibsession_");
-    const char* session_id = st->getCookie(shib_cookie.first);
+    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 {
-            st->getConfig()->getSessionCache()->remove(session_id,st->getApplication(),st->getRemoteAddr());
+            // TODO: port to new cache API
+            //request.getServiceProvider().getSessionCache()->remove(session_id,request.getApplication(),request.getRemoteAddr().c_str());
         }
         catch (exception& e) {
-            st->log(ShibTarget::LogLevelError, 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(ShibTarget::LogLevelError, "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,shib_cookie.second);
+        request.setCookie(shib_cookie.first.c_str(),shib_cookie.second);
     }
     
-    const char* ret=st->getRequestParameter("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));
 }