[cpp-sp] 01/02: Implement local logout.

Codeberg noreply at shibboleth.net
Tue Feb 10 14:02:41 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository cpp-sp.

View the commit online:
https://codeberg.org/Shibboleth/cpp-sp/commit/fca8a7754ab4505a2ffd7e8620ae7e8a27ff2b22

commit fca8a7754ab4505a2ffd7e8620ae7e8a27ff2b22
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 10 09:00:38 2026 -0500

    Implement local logout.
---
 Projects/vc22/shibsp.vcxproj              |   5 +-
 Projects/vc22/shibsp.vcxproj.filters      |  11 ++-
 shibsp/AbstractSPRequest.cpp              |  37 ++++-----
 shibsp/Makefile.am                        |   5 +-
 shibsp/RequestMapper.h                    |   3 +
 shibsp/handler/LogoutHandler.h            |  36 ++++-----
 shibsp/handler/LogoutInitiator.h          |  13 ++--
 shibsp/handler/impl/AbstractHandler.cpp   |  18 +----
 shibsp/handler/impl/LogoutHandler.cpp     | 121 ++++--------------------------
 shibsp/handler/impl/LogoutInitiator.cpp   |  58 +++++++++++++-
 shibsp/handler/impl/MetadataGenerator.cpp |  90 ----------------------
 shibsp/impl/XMLRequestMapper.cpp          |   3 +
 12 files changed, 142 insertions(+), 258 deletions(-)

diff --git a/Projects/vc22/shibsp.vcxproj b/Projects/vc22/shibsp.vcxproj
index 15f163ae..6eac1914 100644
--- a/Projects/vc22/shibsp.vcxproj
+++ b/Projects/vc22/shibsp.vcxproj
@@ -42,6 +42,8 @@
     <ClInclude Include="..\..\shibsp\handler\AbstractHandler.h" />
     <ClInclude Include="..\..\shibsp\handler\AssertionConsumerService.h" />
     <ClInclude Include="..\..\shibsp\handler\Handler.h" />
+    <ClInclude Include="..\..\shibsp\handler\LogoutHandler.h" />
+    <ClInclude Include="..\..\shibsp\handler\LogoutInitiator.h" />
     <ClInclude Include="..\..\shibsp\handler\SecuredHandler.h" />
     <ClInclude Include="..\..\shibsp\internal.h" />
     <ClInclude Include="..\..\shibsp\io\CookieManager.h" />
@@ -97,7 +99,8 @@
     </ClCompile>
     <ClCompile Include="..\..\shibsp\handler\impl\AttributeCheckerHandler.cpp" />
     <ClCompile Include="..\..\shibsp\handler\impl\DefaultHandlerConfiguration.cpp" />
-    <ClCompile Include="..\..\shibsp\handler\impl\MetadataGenerator.cpp" />
+    <ClCompile Include="..\..\shibsp\handler\impl\LogoutHandler.cpp" />
+    <ClCompile Include="..\..\shibsp\handler\impl\LogoutInitiator.cpp" />
     <ClCompile Include="..\..\shibsp\handler\impl\Passthrough.cpp" />
     <ClCompile Include="..\..\shibsp\handler\impl\SecuredHandler.cpp" />
     <ClCompile Include="..\..\shibsp\handler\impl\SessionHandler.cpp" />
diff --git a/Projects/vc22/shibsp.vcxproj.filters b/Projects/vc22/shibsp.vcxproj.filters
index bd1e4f57..d866eac3 100644
--- a/Projects/vc22/shibsp.vcxproj.filters
+++ b/Projects/vc22/shibsp.vcxproj.filters
@@ -117,6 +117,12 @@
     <ClInclude Include="..\..\shibsp\handler\Handler.h">
       <Filter>Header Files\Handler</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\shibsp\handler\LogoutHandler.h">
+      <Filter>Header Files\Handler</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\shibsp\handler\LogoutInitiator.h">
+      <Filter>Header Files\Handler</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\shibsp\handler\SecuredHandler.h">
       <Filter>Header Files\Handler</Filter>
     </ClInclude>
@@ -245,7 +251,10 @@
     <ClCompile Include="..\..\shibsp\handler\impl\AttributeCheckerHandler.cpp">
       <Filter>Source Files\Handler</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\shibsp\handler\impl\MetadataGenerator.cpp">
+    <ClCompile Include="..\..\shibsp\handler\impl\LogoutHandler.cpp">
+      <Filter>Source Files\Handler</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\shibsp\handler\impl\LogoutInitiator.cpp">
       <Filter>Source Files\Handler</Filter>
     </ClCompile>
     <ClCompile Include="..\..\shibsp\handler\impl\Passthrough.cpp">
diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp
index 1f256415..704befd9 100644
--- a/shibsp/AbstractSPRequest.cpp
+++ b/shibsp/AbstractSPRequest.cpp
@@ -127,7 +127,7 @@ const char* AbstractSPRequest::getRequestURL() const
 
 string AbstractSPRequest::getRemoteAddr() const
 {
-    const char* addr = getRequestSettings().first->getString("REMOTE_ADDR");
+    const char* addr = getRequestSettings().first->getString(RequestMapper::REMOTE_ADDR_PROP_NAME);
     return addr ? getHeader(addr) : "";
 }
 
@@ -275,10 +275,10 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
 
 string AbstractSPRequest::getNotificationURL(bool front, unsigned int index) const
 {
-    // We have to process the underlying setting each call to this method unfortunately.
-    const char* rawlocs = getRequestSettings().first->getString(front ? "frontNotifyURLs" : "backNotifyURLs");
+    // We have to process the underlying setting each call to this method for now.
+    // Given how rarely it would be used, not a big issue.
     vector<string> locs;
-    split_to_container(locs, rawlocs);
+    split_to_container(locs, getRequestSettings().first->getString(RequestMapper::LOGOUT_NOTIFY_PROP_NAME));
 
     if (index >= locs.size()) {
         return string();
@@ -293,10 +293,10 @@ string AbstractSPRequest::getNotificationURL(bool front, unsigned int index) con
 
     // Should never happen...
     if (!handler || (*handler!='/' && strncasecmp(handler, "http:", 5) && strncasecmp(handler, "https:", 6))) {
-        throw ConfigurationException("Invalid Location property in Notify element");
+        throw ConfigurationException("Invalid URL in logoutNotify setting.");
     }
 
-    // The "Location" property can be in one of three formats:
+    // The location can be in one of three formats:
     //
     // 1) a full URI:       http://host/foo/bar
     // 2) a hostless URI:   http:///foo/bar
@@ -347,6 +347,8 @@ string AbstractSPRequest::getNotificationURL(bool front, unsigned int index) con
 
 void AbstractSPRequest::limitRedirect(const char* url) const
 {
+    // TODO: come up with some way to optmize/cache this if possible.
+
     if (!url || *url == '/') {
         return;
     }
@@ -444,9 +446,19 @@ string AbstractSPRequest::getSecureHeader(const char* name) const
     return getHeader(name);
 }
 
-void AbstractSPRequest::setAuthType(const char* authtype)
+string AbstractSPRequest::getCGINameForHeader(const char* name) const
 {
+    string cgiversion("HTTP_");
+    const char* pch = name;
+    while (*pch) {
+        cgiversion += (isalnum(*pch) ? toupper(*pch) : '_');
+        pch++;
+    }
+    return cgiversion;
+}
 
+void AbstractSPRequest::setAuthType(const char* authtype)
+{
 }
 
 const char* AbstractSPRequest::getLogContext() const{
@@ -582,14 +594,3 @@ void SPRequest::crit(const char* formatString, ...) const
         va_end(va);
     }
 }
-
-string AbstractSPRequest::getCGINameForHeader(const char* name) const
-{
-    string cgiversion("HTTP_");
-    const char* pch = name;
-    while (*pch) {
-        cgiversion += (isalnum(*pch) ? toupper(*pch) : '_');
-        pch++;
-    }
-    return cgiversion;
-}
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index 70d2303a..b60ef307 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -43,6 +43,8 @@ handinclude_HEADERS = \
 	handler/AssertionConsumerService.h \
 	handler/Handler.h \
 	handler/HandlerConfiguration.h \
+	handler/LogoutHandler.h \
+	handler/LogoutInitiator.h \
 	handler/SecuredHandler.h
 
 ioinclude_HEADERS = \
@@ -106,7 +108,8 @@ libshibsp_la_SOURCES = \
 	handler/impl/AbstractHandler.cpp \
 	handler/impl/AttributeCheckerHandler.cpp \
 	handler/impl/DefaultHandlerConfiguration.cpp \
-	handler/impl/MetadataGenerator.cpp \
+	handler/impl/LogoutHandler.cpp \
+	handler/impl/LogoutInitiator.cpp \
 	handler/impl/Passthrough.cpp \
 	handler/impl/SecuredHandler.cpp \
 	handler/impl/SessionHandler.cpp \
diff --git a/shibsp/RequestMapper.h b/shibsp/RequestMapper.h
index 88095ea9..ebd930bb 100644
--- a/shibsp/RequestMapper.h
+++ b/shibsp/RequestMapper.h
@@ -60,12 +60,15 @@ namespace shibsp {
         static const char HANDLER_URL_PROP_NAME[];
         static const char HOME_URL_PROP_NAME[];
         static const char LIFETIME_PROP_NAME[];
+        static const char LOGOUT_NOTIFY_PROP_NAME[];
+        static const char LOGOUT_URL_PROP_NAME[];
         static const char PRESERVE_POST_DATA_PROP_NAME[];
         static const char POST_LIMIT_PROP_NAME[];
         static const char REDIRECT_ALLOW_PROP_NAME[];
         static const char REDIRECT_ERRORS_PROP_NAME[];
         static const char REDIRECT_LIMIT_PROP_NAME[];
         static const char REDIRECT_TO_SSL_PROP_NAME[];
+        static const char REMOTE_ADDR_PROP_NAME[];
         static const char REMOTE_USER_PROP_NAME[];
         static const char REQUIRE_SESSION_PROP_NAME[];
         static const char REQUIRE_LOGOUT_WITH_PROP_NAME[];
diff --git a/shibsp/handler/LogoutHandler.h b/shibsp/handler/LogoutHandler.h
index 67a3f8dc..a52e8ac8 100644
--- a/shibsp/handler/LogoutHandler.h
+++ b/shibsp/handler/LogoutHandler.h
@@ -21,7 +21,11 @@
 #ifndef __shibsp_logout_h__
 #define __shibsp_logout_h__
 
-#include <shibsp/handler/RemotedHandler.h>
+#include <shibsp/handler/Handler.h>
+
+#include <map>
+#include <string>
+#include <vector>
 
 namespace shibsp {
 
@@ -31,24 +35,25 @@ namespace shibsp {
 #endif
 
     /**
-     * Base class for logout-related handlers.
+     * Base class for logout-related handlers, both when initiating from the
+     * Agent or processing incoming requests or responses from other systems.
      */
-    class SHIBSP_API LogoutHandler
+    class SHIBSP_API LogoutHandler : public virtual Handler
     {
     public:
         virtual ~LogoutHandler();
 
         /**
          * The base method will iteratively attempt front-channel notification
-         * of logout of the current session, and after the final round trip will
-         * perform back-channel notification. Nothing will be done unless the 
-         * handler detects that it is the "top" level logout handler.
-         * If the method returns false, then the specialized class should perform
-         * its work assuming that the notifications are completed.
+         * of logout of the current session.
+         * 
+         * <p>Nothing will be done unless the handler detects that it is the "top" level
+         * logout handler. If the method returns false, then the specialized class should
+         * perform its work assuming that the notifications are completed.</p>
          *
-         * Note that the current session is NOT removed from the cache.
+         * <p>Note that the current session is NOT removed from the cache.</p>
          * 
-         * @param request   SP request context
+         * @param request   SP request
          * @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
          */
@@ -74,17 +79,6 @@ namespace shibsp {
             SPRequest& request, const std::map<std::string,std::string>* params=nullptr
             ) const;
 
-        /**
-         * Perform back-channel logout notifications for an Application.
-         *
-         * @param request       request resulting in method call
-         * @param sessions      array of session keys being logged out
-         * @param local         true iff the logout operation is local to the SP, false iff global
-         * @return  true iff all notifications succeeded
-         */
-        bool notifyBackChannel(
-            const SPRequest& request, const std::vector<std::string>& sessions, bool local
-            ) const;
     };
 
 #if defined (_MSC_VER)
diff --git a/shibsp/handler/LogoutInitiator.h b/shibsp/handler/LogoutInitiator.h
index e0b11102..9dc4c853 100644
--- a/shibsp/handler/LogoutInitiator.h
+++ b/shibsp/handler/LogoutInitiator.h
@@ -15,7 +15,7 @@
 /**
  * @file shibsp/handler/LogoutInitiator.h
  * 
- * Pluggable runtime functionality that handles initiating logout.
+ * Handler that initiates logout.
  */
 
 #ifndef __shibsp_logoutinitiator_h__
@@ -23,17 +23,20 @@
 
 #include <shibsp/handler/LogoutHandler.h>
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 namespace shibsp {
 
     /**
-     * Pluggable runtime functionality that handles initiating logout.
+     * Marker interface for handlers that can initiate logout.
      */
-    class SHIBSP_API LogoutInitiator : public LogoutHandler
+    class SHIBSP_API LogoutInitiator : public virtual LogoutHandler
     {
-    protected:
-        LogoutInitiator();
     public:
+        LogoutInitiator(const boost::property_tree::ptree& pt);
         virtual ~LogoutInitiator();
+
+        std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
     };
 
 };
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 055a28cf..5242517a 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -47,20 +47,15 @@ using namespace std;
 #endif
 
 namespace shibsp {
-    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutFactory;
-    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AttributeCheckerFactory;
-    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory MetadataGeneratorFactory;
-
     //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AdminLogoutInitiatorFactory;
-    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SAML2LogoutInitiatorFactory;
-    //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory LocalLogoutInitiatorFactory;
 
+    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AttributeCheckerFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory PassthroughFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionHandlerFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory StatusHandlerFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionInitiatorFactory;
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory TokenConsumerFactory;
-
+    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory LogoutInitiatorFactory;
 
     void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {
         static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
@@ -83,20 +78,15 @@ void SHIBSP_API shibsp::registerHandlers()
 {
     AgentConfig& conf=AgentConfig::getConfig();
 
-    //conf.HandlerManager.registerFactory(ATTR_CHECKER_HANDLER, AttributeCheckerFactory);
-    //conf.HandlerManager.registerFactory(METADATA_GENERATOR_HANDLER, MetadataGeneratorFactory);
- 
-    //conf.HandlerManager.registerFactory(SAML20_LOGOUT_HANDLER, SAML2LogoutFactory);
-
     //conf.HandlerManager.registerFactory(ADMIN_LOGOUT_INITIATOR, AdminLogoutInitiatorFactory);
-    //conf.HandlerManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
-    //conf.HandlerManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
 
+    conf.HandlerManager.registerFactory(ATTR_CHECKER_HANDLER, AttributeCheckerFactory);
     conf.HandlerManager.registerFactory(PASSTHROUGH_HANDLER, PassthroughFactory);
     conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
     conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);
     conf.HandlerManager.registerFactory(SESSION_INITIATOR_HANDLER, SessionInitiatorFactory);
     conf.HandlerManager.registerFactory(TOKEN_CONSUMER_HANDLER, TokenConsumerFactory);
+    conf.HandlerManager.registerFactory(LOGOUT_INITIATOR_HANDLER, LogoutInitiatorFactory);
 } 
 
 Handler::Handler()
diff --git a/shibsp/handler/impl/LogoutHandler.cpp b/shibsp/handler/impl/LogoutHandler.cpp
index a98eebf3..ead053d7 100644
--- a/shibsp/handler/impl/LogoutHandler.cpp
+++ b/shibsp/handler/impl/LogoutHandler.cpp
@@ -23,9 +23,6 @@
 #include "AgentConfig.h"
 #include "SPRequest.h"
 #include "handler/LogoutHandler.h"
-#include "logging/Category.h"
-#include "session/SessionCache.h"
-#include "util/PathResolver.h"
 #include "util/URLEncoder.h"
 
 #include <fstream>
@@ -52,46 +49,23 @@ pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
     return notifyFrontChannel(request);
 }
 
-/*
-void LogoutHandler::receive(DDF& in, ostream& out)
-{
-    DDF ret(nullptr);
-    DDFJanitor jout(ret);
-    if (in["notify"].integer() != 1)
-        throw RemotintgException("Unsupported operation.");
-
-    vector<string> sessions;
-    DDF s = in["sessions"];
-    DDF temp = s.first();
-    while (temp.isstring()) {
-        sessions.push_back(temp.string());
-        temp = s.next();
-        //if (notifyBackChannel(*app, in["url"].string(), sessions, in["local"].integer()==1))
-            //ret.integer(1);
-    }
-
-    out << ret;
-}
-*/
-
-pair<bool,long> LogoutHandler::notifyFrontChannel(
-    SPRequest& request,
-    const map<string,string>* params
-    ) const
+pair<bool,long> LogoutHandler::notifyFrontChannel(SPRequest& request, const map<string,string>* params) const
 {
     // Index of notification point starts at 0.
     unsigned int index = 0;
     const char* param = request.getParameter("index");
-    if (param)
+    if (param && isdigit(*param)) {
         index = atoi(param);
+    }
 
     // "return" is a backwards-compatible "eventual destination" to go back to after logout completes.
     param = request.getParameter("return");
 
     // Fetch the next front notification URL and bump the index for the next round trip.
     string loc = request.getNotificationURL(true, index++);
-    if (loc.empty())
+    if (loc.empty()) {
         return make_pair(false,0L);
+    }
 
     const URLEncoder& encoder = AgentConfig::getConfig().getURLEncoder();
 
@@ -107,19 +81,22 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
     locstr = locstr + "?notifying=1&index=" + boost::lexical_cast<string>(index);
 
     // Add return if set.
-    if (param)
+    if (param) {
         locstr = locstr + "&return=" + encoder.encode(param);
+    }
 
     // We preserve anything we're instructed to directly.
     if (params) {
-        for (map<string,string>::const_iterator p = params->begin(); p!=params->end(); ++p)
-            locstr = locstr + '&' + p->first + '=' + encoder.encode(p->second.c_str());
+        for (const auto& p : *params) {
+            locstr = locstr + '&' + p.first + '=' + encoder.encode(p.second.c_str());
+        }
     }
     else {
-        for (vector<string>::const_iterator q = m_preserve.begin(); q!=m_preserve.end(); ++q) {
-            param = request.getParameter(q->c_str());
-            if (param)
-                locstr = locstr + '&' + *q + '=' + encoder.encode(param);
+        for (const auto& q : m_preserve) {
+            param = request.getParameter(q.c_str());
+            if (param) {
+                locstr = locstr + '&' + q + '=' + encoder.encode(param);
+            }
         }
     }
 
@@ -128,71 +105,3 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
     loc = loc + "&return=" + encoder.encode(locstr.c_str());
     return make_pair(true, request.sendRedirect(loc.c_str()));
 }
-
-bool LogoutHandler::notifyBackChannel(const SPRequest& request, const vector<string>& sessions, bool local) const
-{
-    if (sessions.empty()) {
-        Category::getInstance(SHIBSP_LOGCAT ".Logout").error("no sessions supplied to back channel notification method");
-        return false;
-    }
-
-    unsigned int index = 0;
-    string endpoint = request.getNotificationURL(false, index++);
-    if (endpoint.empty())
-        return true;
-
-    if (false) {
-#ifndef SHIBSP_LITE
-        scoped_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
-        Body* body = BodyBuilder::buildBody();
-        env->setBody(body);
-        ElementProxy* msg = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, LogoutNotification);
-        body->getUnknownXMLObjects().push_back(msg);
-        msg->setAttribute(xmltooling::QName(nullptr, _type), local ? _local : _global);
-        for (vector<string>::const_iterator s = sessions.begin(); s != sessions.end(); ++s) {
-            auto_ptr_XMLCh temp(s->c_str());
-            ElementProxy* child = new AnyElementImpl(shibspconstants::SHIB2SPNOTIFY_NS, SessionID);
-            child->setTextContent(temp.get());
-            msg->getUnknownXMLObjects().push_back(child);
-        }
-
-        bool result = true;
-        SOAPNotifier soaper;
-        while (!endpoint.empty()) {
-            try {
-                soaper.send(*env, SOAPTransport::Address(application.getId(), application.getId(), endpoint.c_str()));
-                delete soaper.receive();
-            }
-            catch (std::exception& ex) {
-                Category::getInstance(SHIBSP_LOGCAT ".Logout").error("error notifying application of logout event: %s", ex.what());
-                result = false;
-            }
-            soaper.reset();
-            endpoint = application.getNotificationURL(requestURL, false, index++);
-        }
-        return result;
-#else
-        return false;
-#endif
-    }
-
-/*
-    // When not out of process, we remote the back channel work.
-    // TODO: remove anyway....
-    DDF out,in(m_address.c_str());
-    DDFJanitor jin(in), jout(out);
-    in.addmember("notify").integer(1);
-    //in.addmember("application_id").string(application.getId());
-    in.addmember("url").string(request.getRequestURL());
-    if (local)
-        in.addmember("local").integer(1);
-    DDF s = in.addmember("sessions").list();
-    for (vector<string>::const_iterator i = sessions.begin(); i!=sessions.end(); ++i) {
-        DDF temp = DDF(nullptr).string(i->c_str());
-        s.add(temp);
-    }
-    //out = application.getServiceProvider().getListenerService()->send(in);
-    return (out.integer() == 1);
-*/
-return false;
-}
diff --git a/shibsp/handler/impl/LogoutInitiator.cpp b/shibsp/handler/impl/LogoutInitiator.cpp
index 5aaacd83..547e9b6f 100644
--- a/shibsp/handler/impl/LogoutInitiator.cpp
+++ b/shibsp/handler/impl/LogoutInitiator.cpp
@@ -19,14 +19,70 @@
  */
 
 #include "internal.h"
+#include "Agent.h"
+#include "SPRequest.h"
 #include "handler/LogoutInitiator.h"
+#include "session/SessionCache.h"
+
+#include <boost/property_tree/ptree.hpp>
 
 using namespace shibsp;
+using namespace boost::property_tree;
+using namespace std;
+
+namespace shibsp {
+    Handler* SHIBSP_DLLLOCAL LogoutInitiatorFactory(const pair<ptree&,const char*>& p, bool)
+    {
+        return new LogoutInitiator(p.first);
+    }
+}
 
-LogoutInitiator::LogoutInitiator()
+LogoutInitiator::LogoutInitiator(const ptree& pt)
 {
 }
 
 LogoutInitiator::~LogoutInitiator()
 {
 }
+
+pair<bool,long> LogoutInitiator::run(SPRequest& request, bool isHandler) const
+{
+    // Defer to base class first; this will initiate, continue, or complete notification.
+    pair<bool,long> ret = LogoutHandler::run(request, isHandler);
+    if (ret.first) {
+        return ret;
+    }
+
+    unique_lock<Session> session;
+    try {
+        session = request.getSession(false, true);  // don't cache it and ignore all checks
+    }
+    catch (const exception& ex) {
+        request.error("error accessing current session: %s", ex.what());
+    }
+
+    if (session) {
+        session.unlock();
+        request.getAgent().getSessionCache()->remove(request);
+    }
+
+    // Determine return location.
+    const char* dest = request.getParameter("return");
+    if (!dest) {
+        dest = request.getRequestSettings().first->getString(RequestMapper::LOGOUT_URL_PROP_NAME);
+        if (!dest) {
+            dest = request.getRequestSettings().first->getString(RequestMapper::HOME_URL_PROP_NAME,
+                RequestMapper::HOME_URL_PROP_DEFAULT);
+        }
+    }
+
+    // Relative URLs get promoted, absolutes get validated.
+    if (*dest == '/') {
+        string d(dest);
+        request.absolutize(d);
+        return make_pair(true, request.sendRedirect(d.c_str()));
+    } else {
+        request.limitRedirect(dest);
+        return make_pair(true, request.sendRedirect(dest));
+    }
+}
diff --git a/shibsp/handler/impl/MetadataGenerator.cpp b/shibsp/handler/impl/MetadataGenerator.cpp
deleted file mode 100644
index 8de268b9..00000000
--- a/shibsp/handler/impl/MetadataGenerator.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * handler/impl/MetadataGenerator.cpp
- *
- * Handler for generating "approximate" metadata based on SP configuration.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "SPRequest.h"
-#include "handler/SecuredHandler.h"
-#include "logging/Category.h"
-#include "util/Misc.h"
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-using namespace shibsp;
-using namespace boost::property_tree;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
-
-    class SHIBSP_API MetadataGenerator : public SecuredHandler
-    {
-    public:
-        MetadataGenerator(const ptree& pt);
-        virtual ~MetadataGenerator() {}
-
-        pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
-    private:
-        vector<string> m_bases;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    Handler* SHIBSP_DLLLOCAL MetadataGeneratorFactory(const pair<ptree&,const char*>& p, bool)
-    {
-        return new MetadataGenerator(p.first);
-    }
-
-};
-
-MetadataGenerator::MetadataGenerator(const ptree& pt) : SecuredHandler(pt)
-{
-    const char* bases = getString("baseURLs");
-    if (bases) {
-        split_to_container(m_bases, bases);
-    }
-}
-
-pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
-{
-    // Check ACL in base class.
-    pair<bool,long> ret = SecuredHandler::run(request, isHandler);
-    if (ret.first)
-        return ret;
-
-    try {
-        // TODO
-    }
-    catch (const exception& ex) {
-        request.error(string("error while processing request: ") + ex.what());
-        istringstream msg("Metadata Request Failed");
-        return make_pair(true, request.sendResponse(msg, HTTPResponse::SHIBSP_HTTP_STATUS_ERROR));
-    }
-    return ret;
-}
diff --git a/shibsp/impl/XMLRequestMapper.cpp b/shibsp/impl/XMLRequestMapper.cpp
index 7a386795..f8d70c3a 100644
--- a/shibsp/impl/XMLRequestMapper.cpp
+++ b/shibsp/impl/XMLRequestMapper.cpp
@@ -179,12 +179,15 @@ const char RequestMapper::HANDLER_URL_PROP_NAME[] =         "handlerURL";
 const char RequestMapper::HOME_URL_PROP_NAME[] =            "homeURL";
 const char RequestMapper::EXPIRE_REDIRECTS_PROP_NAME[] =    "expireRedirects";
 const char RequestMapper::LIFETIME_PROP_NAME[] =            "lifetime";
+const char RequestMapper::LOGOUT_NOTIFY_PROP_NAME[] =       "logoutNotify";
+const char RequestMapper::LOGOUT_URL_PROP_NAME[] =          "logoutURL";
 const char RequestMapper::PRESERVE_POST_DATA_PROP_NAME[] =  "preservePostData";
 const char RequestMapper::POST_LIMIT_PROP_NAME[] =          "postLimit";
 const char RequestMapper::REDIRECT_ALLOW_PROP_NAME[] =      "redirectAllow";
 const char RequestMapper::REDIRECT_ERRORS_PROP_NAME[] =     "redirectErrors";
 const char RequestMapper::REDIRECT_LIMIT_PROP_NAME[] =      "redirectLimit";
 const char RequestMapper::REDIRECT_TO_SSL_PROP_NAME[] =     "redirectToSSL";
+const char RequestMapper::REMOTE_ADDR_PROP_NAME[] =         "REMOTE_ADDR";
 const char RequestMapper::REMOTE_USER_PROP_NAME[] =         "REMOTE_USER";
 const char RequestMapper::REQUIRE_LOGOUT_WITH_PROP_NAME[] = "requireLogoutWith";
 const char RequestMapper::REQUIRE_SESSION_PROP_NAME[] =     "requireSession";

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list