Factor out LogoutInitiator class, simpler API to get ACS by binding.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 12 Aug 2010 01:00:58 +0000 (01:00 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 12 Aug 2010 01:00:58 +0000 (01:00 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@3291 cb58f699-b61c-0410-a6fe-9272a202ed29

21 files changed:
adfs/adfs.cpp
shibsp/Application.cpp
shibsp/Application.h
shibsp/Makefile.am
shibsp/SPConfig.cpp
shibsp/handler/LogoutHandler.h
shibsp/handler/LogoutInitiator.h [new file with mode: 0644]
shibsp/handler/SessionInitiator.h
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/ChainingLogoutInitiator.cpp
shibsp/handler/impl/LocalLogoutInitiator.cpp
shibsp/handler/impl/LogoutInitiator.cpp [new file with mode: 0644]
shibsp/handler/impl/SAML2LogoutInitiator.cpp
shibsp/handler/impl/SAML2SessionInitiator.cpp
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/handler/impl/WAYFSessionInitiator.cpp
shibsp/impl/XMLServiceProvider.cpp
shibsp/shibsp-lite.vcxproj
shibsp/shibsp-lite.vcxproj.filters
shibsp/shibsp.vcxproj
shibsp/shibsp.vcxproj.filters

index 333249f..c8f4bdd 100644 (file)
@@ -42,7 +42,7 @@
 #include <shibsp/SPConfig.h>
 #include <shibsp/SPRequest.h>
 #include <shibsp/handler/AssertionConsumerService.h>
-#include <shibsp/handler/LogoutHandler.h>
+#include <shibsp/handler/LogoutInitiator.h>
 #include <shibsp/handler/SessionInitiator.h>
 #include <xmltooling/logging.h>
 #include <xmltooling/util/DateTime.h>
@@ -118,7 +118,7 @@ namespace {
     {
     public:
         ADFSSessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS"), nullptr, &m_remapper), m_appId(appId), m_binding(WSFED_NS) {
+            : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS"), nullptr, &m_remapper), m_appId(appId), m_binding(WSFED_NS) {
             // If Location isn't set, defer address registration until the setParent call.
             pair<bool,const char*> loc = getString("Location");
             if (loc.first) {
@@ -192,7 +192,7 @@ namespace {
 #endif
     };
 
-    class SHIBSP_DLLLOCAL ADFSLogoutInitiator : public AbstractHandler, public LogoutHandler
+    class SHIBSP_DLLLOCAL ADFSLogoutInitiator : public AbstractHandler, public LogoutInitiator
     {
     public:
         ADFSLogoutInitiator(const DOMElement* e, const char* appId)
@@ -221,11 +221,6 @@ namespace {
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
-#ifndef SHIBSP_LITE
-        const char* getType() const {
-            return "LogoutInitiator";
-        }
-#endif
         const XMLCh* getProtocolFamily() const {
             return m_binding.get();
         }
@@ -381,12 +376,11 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
                 request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
         }
         if (!ACS) {
-            const vector<const Handler*>& endpoints = app.getAssertionConsumerServicesByBinding(m_binding.get());
-            if (endpoints.empty()) {
+            ACS = app.getAssertionConsumerServiceByBinding(WSFED_NS);
+            if (!ACS) {
                 m_log.error("unable to locate a compatible ACS");
                 throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration.");
             }
-            ACS = endpoints.front();
         }
     }
 
index 439cd73..f13e1f1 100644 (file)
@@ -133,3 +133,10 @@ void Application::clearAttributeHeaders(SPRequest& request) const
     for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
         request.clearHeader(i->first.c_str(), i->second.c_str());
 }
+
+const Handler* Application::getAssertionConsumerServiceByBinding(const char* binding) const
+{
+    auto_ptr_XMLCh b(binding);
+    const vector<const Handler*>& handlers = getAssertionConsumerServicesByBinding(b.get());
+    return handlers.empty() ? nullptr : handlers.front();
+}
index 9669a3b..29ae8e2 100644 (file)
@@ -282,6 +282,16 @@ namespace shibsp {
         virtual const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const=0;
 
         /**
+         * Returns an AssertionConsumerService Handler that supports
+         * a particular protocol binding.
+         *
+         * @param binding   a protocol binding identifier
+         * @return a matching AssertionConsumerService, or nullptr
+         */
+        virtual const Handler* getAssertionConsumerServiceByBinding(const char* binding) const;
+
+        /**
+         * @deprecated
          * Returns one or more AssertionConsumerService Handlers that support
          * a particular protocol binding.
          *
index 7184a59..39ca0e2 100644 (file)
@@ -70,6 +70,7 @@ handinclude_HEADERS = \
        handler/AssertionConsumerService.h \
        handler/Handler.h \
        handler/LogoutHandler.h \
+       handler/LogoutInitiator.h \
        handler/RemotedHandler.h \
        handler/SessionInitiator.h
 
@@ -121,6 +122,7 @@ common_sources = \
        handler/impl/FormSessionInitiator.cpp \
        handler/impl/LocalLogoutInitiator.cpp \
        handler/impl/LogoutHandler.cpp \
+       handler/impl/LogoutInitiator.cpp \
        handler/impl/MetadataGenerator.cpp \
        handler/impl/RemotedHandler.cpp \
        handler/impl/StatusHandler.cpp \
index f89ee17..55e15e5 100644 (file)
@@ -43,6 +43,7 @@
 #include "SPConfig.h"
 #include "TransactionLog.h"
 #include "attribute/Attribute.h"
+#include "handler/LogoutInitiator.h"
 #include "handler/SessionInitiator.h"
 #include "remoting/ListenerService.h"
 
@@ -241,6 +242,7 @@ bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
 
     registerAttributeFactories();
     registerHandlers();
+    registerLogoutInitiators();
     registerSessionInitiators();
     registerServiceProviders();
 
index e23f7db..e4e5a02 100644 (file)
@@ -142,16 +142,6 @@ namespace shibsp {
 #if defined (_MSC_VER)
     #pragma warning( pop )
 #endif
-
-    /** LogoutInitiator that iterates through a set of protocol-specific versions. */
-    #define CHAINING_LOGOUT_INITIATOR "Chaining"
-
-    /** LogoutInitiator that supports SAML 2.0 LogoutRequests. */
-    #define SAML2_LOGOUT_INITIATOR "SAML2"
-
-    /** LogoutInitiator that supports local-only logout. */
-    #define LOCAL_LOGOUT_INITIATOR "Local"
-
 };
 
 #endif /* __shibsp_logout_h__ */
diff --git a/shibsp/handler/LogoutInitiator.h b/shibsp/handler/LogoutInitiator.h
new file mode 100644 (file)
index 0000000..fcf9fc8
--- /dev/null
@@ -0,0 +1,58 @@
+/*\r
+ *  Copyright 2010 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file shibsp/handler/LogoutInitiator.h\r
+ * \r
+ * Pluggable runtime functionality that handles initiating logout.\r
+ */\r
+\r
+#ifndef __shibsp_logoutinitiator_h__\r
+#define __shibsp_logoutinitiator_h__\r
+\r
+#include <shibsp/handler/LogoutHandler.h>\r
+\r
+namespace shibsp {\r
+\r
+    /**\r
+     * Pluggable runtime functionality that handles initiating logout.\r
+     */\r
+    class SHIBSP_API LogoutInitiator : public LogoutHandler\r
+    {\r
+    protected:\r
+        LogoutInitiator();\r
+    public:\r
+        virtual ~LogoutInitiator();\r
+\r
+#ifndef SHIBSP_LITE\r
+        const char* getType() const;\r
+#endif\r
+    };\r
+    \r
+    /** Registers LogoutInitiator implementations. */\r
+    void SHIBSP_API registerLogoutInitiators();\r
+\r
+    /** LogoutInitiator that iterates through a set of protocol-specific versions. */\r
+    #define CHAINING_LOGOUT_INITIATOR "Chaining"\r
+\r
+    /** LogoutInitiator that supports SAML 2.0 LogoutRequests. */\r
+    #define SAML2_LOGOUT_INITIATOR "SAML2"\r
+\r
+    /** LogoutInitiator that supports local-only logout. */\r
+    #define LOCAL_LOGOUT_INITIATOR "Local"\r
+};\r
+\r
+#endif /* __shibsp_logoutinitiator_h__ */\r
index d31d988..33b310a 100644 (file)
  * Pluggable runtime functionality that handles initiating sessions.
  */
 
-#ifndef __shibsp_initiator_h__
-#define __shibsp_initiator_h__
+#ifndef __shibsp_sesinitiator_h__
+#define __shibsp_sesinitiator_h__
 
 #include <shibsp/handler/Handler.h>
 
+#include <map>
 #include <set>
 #include <string>
 
@@ -66,7 +67,7 @@ namespace shibsp {
         /**
          * Indicates the set of optional settings supported by the handler.
          *
-         * @return  an array of the optional settings supported
+         * @return  a set of the optional settings supported
          */
         virtual const std::set<std::string>& getSupportedOptions() const;
 
@@ -118,4 +119,4 @@ namespace shibsp {
     #define COOKIE_SESSION_INITIATOR "Cookie"
 };
 
-#endif /* __shibsp_initiator_h__ */
+#endif /* __shibsp_sesinitiator_h__ */
index a2e5439..0763746 100644 (file)
@@ -67,12 +67,10 @@ using namespace xercesc;
 using namespace std;
 
 namespace shibsp {
+
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;
     SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;
@@ -134,9 +132,6 @@ void SHIBSP_API shibsp::registerHandlers()
     conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
     conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);
 
-    conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);
     conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);
index 2475787..4b8365a 100644 (file)
@@ -23,7 +23,7 @@
 #include "internal.h"
 #include "exceptions.h"
 #include "handler/AbstractHandler.h"
-#include "handler/LogoutHandler.h"
+#include "handler/LogoutInitiator.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -40,7 +40,7 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class SHIBSP_DLLLOCAL ChainingLogoutInitiator : public AbstractHandler, public LogoutHandler
+    class SHIBSP_DLLLOCAL ChainingLogoutInitiator : public AbstractHandler, public LogoutInitiator
     {
     public:
         ChainingLogoutInitiator(const DOMElement* e, const char* appId);
@@ -51,10 +51,6 @@ namespace shibsp {
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
 #ifndef SHIBSP_LITE
-        const char* getType() const {
-            return "LogoutInitiator";
-        }
-
         void generateMetadata(opensaml::saml2md::SPSSODescriptor& role, const char* handlerURL) const {
             for (vector<Handler*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i)
                 (*i)->generateMetadata(role, handlerURL);
@@ -101,12 +97,12 @@ ChainingLogoutInitiator::ChainingLogoutInitiator(const DOMElement* e, const char
     SPConfig& conf = SPConfig::getConfig();
 
     // Load up the chain of handlers.
-    e = e ? XMLHelper::getFirstChildElement(e, _LogoutInitiator) : nullptr;
+    e = XMLHelper::getFirstChildElement(e, _LogoutInitiator);
     while (e) {
-        auto_ptr_char type(e->getAttributeNS(nullptr,_type));
-        if (type.get() && *(type.get())) {
+        string t(XMLHelper::getAttrString(e, nullptr, _type));
+        if (!t.empty()) {
             try {
-                m_handlers.push_back(conf.LogoutInitiatorManager.newPlugin(type.get(),make_pair(e, appId)));
+                m_handlers.push_back(conf.LogoutInitiatorManager.newPlugin(t.c_str(), make_pair(e, appId)));
                 m_handlers.back()->setParent(this);
             }
             catch (exception& ex) {
index 47345c7..5468df9 100644 (file)
@@ -26,7 +26,7 @@
 #include "SessionCache.h"
 #include "SPRequest.h"
 #include "handler/AbstractHandler.h"
-#include "handler/LogoutHandler.h"
+#include "handler/LogoutInitiator.h"
 
 using namespace shibsp;
 using namespace xmltooling;
@@ -39,7 +39,7 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class SHIBSP_DLLLOCAL LocalLogoutInitiator : public AbstractHandler, public LogoutHandler
+    class SHIBSP_DLLLOCAL LocalLogoutInitiator : public AbstractHandler, public LogoutInitiator
     {
     public:
         LocalLogoutInitiator(const DOMElement* e, const char* appId);
@@ -48,12 +48,6 @@ namespace shibsp {
         void setParent(const PropertySet* parent);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
-#ifndef SHIBSP_LITE
-        const char* getType() const {
-            return "LogoutInitiator";
-        }
-#endif
-
     private:
         string m_appId;
     };
diff --git a/shibsp/handler/impl/LogoutInitiator.cpp b/shibsp/handler/impl/LogoutInitiator.cpp
new file mode 100644 (file)
index 0000000..efcb86b
--- /dev/null
@@ -0,0 +1,57 @@
+/*\r
+ *  Copyright 2010 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * LogoutInitiator.cpp\r
+ * \r
+ * Pluggable runtime functionality that handles initiating logout.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "handler/LogoutInitiator.h"\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;\r
+};\r
+\r
+void SHIBSP_API shibsp::registerLogoutInitiators()\r
+{\r
+    SPConfig& conf=SPConfig::getConfig();\r
+    conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);\r
+    conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);\r
+    conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);\r
+}\r
+\r
+LogoutInitiator::LogoutInitiator()\r
+{\r
+}\r
+\r
+LogoutInitiator::~LogoutInitiator()\r
+{\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+const char* LogoutInitiator::getType() const\r
+{\r
+    return "LogoutInitiator";\r
+}\r
+#endif\r
index 66528a0..cba23f6 100644 (file)
@@ -26,7 +26,7 @@
 #include "ServiceProvider.h"
 #include "SessionCache.h"
 #include "handler/AbstractHandler.h"
-#include "handler/LogoutHandler.h"
+#include "handler/LogoutInitiator.h"
 
 #ifndef SHIBSP_LITE
 # include "binding/SOAPClient.h"
@@ -58,7 +58,7 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class SHIBSP_DLLLOCAL SAML2LogoutInitiator : public AbstractHandler, public LogoutHandler
+    class SHIBSP_DLLLOCAL SAML2LogoutInitiator : public AbstractHandler, public LogoutInitiator
     {
     public:
         SAML2LogoutInitiator(const DOMElement* e, const char* appId);
@@ -75,11 +75,6 @@ namespace shibsp {
         void receive(DDF& in, ostream& out);
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
-#ifndef SHIBSP_LITE
-        const char* getType() const {
-            return "LogoutInitiator";
-        }
-#endif
         const XMLCh* getProtocolFamily() const {
             return samlconstants::SAML20P_NS;
         }
index 17056a2..9707700 100644 (file)
@@ -42,7 +42,7 @@ using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 #else
 # include "lite/SAMLConstants.h"
-#include <xercesc/util/XMLUniDefs.hpp>
+# include <xercesc/util/XMLUniDefs.hpp>
 #endif
 
 using namespace shibsp;
@@ -310,18 +310,25 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
 
     if (!ACS) {
         if (ECP) {
-            const vector<const Handler*>& handlers = app.getAssertionConsumerServicesByBinding(m_paosBinding.get());
-            if (handlers.empty())
+            ACS = app.getAssertionConsumerServiceByBinding(samlconstants::SAML20_BINDING_PAOS);
+            if (!ACS)
                 throw ConfigurationException("Unable to locate PAOS response endpoint.");
-            ACS = handlers.front();
         }
         else {
+            // Try fixed index property, or incoming binding set, or default, in order.
             pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
             if (index.first) {
                 ACS = app.getAssertionConsumerServiceByIndex(index.second);
                 if (!ACS)
                     request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
             }
+            /*
+            for (vector<string>::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) {
+                ACS = app.getAssertionConsumerServiceByBinding(b->c_str());
+                if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily()))
+                    ACS = nullptr;
+            }
+            */
             if (!ACS)
                 ACS = app.getDefaultAssertionConsumerService();
         }
index 21a1703..e4ac2e8 100644 (file)
@@ -151,12 +151,20 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
 
     // Since we're not passing by index, we need to fully compute the return URL.
     if (!ACS) {
+        // Try fixed index property, or incoming binding set, or default, in order.
         pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
         if (index.first) {
             ACS = app.getAssertionConsumerServiceByIndex(index.second);
             if (!ACS)
                 request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
         }
+        /*
+        for (vector<string>::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) {
+            ACS = app.getAssertionConsumerServiceByBinding(b->c_str());
+            if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily()))
+                ACS = nullptr;
+        }
+        */
         if (!ACS)
             ACS = app.getDefaultAssertionConsumerService();
     }
index 160000d..534a311 100644 (file)
@@ -124,12 +124,20 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     
     // Since we're not passing by index, we need to fully compute the return URL.
     if (!ACS) {
+        // Try fixed index property, or incoming binding set, or default, in order.
         pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
         if (index.first) {
             ACS = app.getAssertionConsumerServiceByIndex(index.second);
             if (!ACS)
                 request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
         }
+        /*
+        for (vector<string>::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) {
+            ACS = app.getAssertionConsumerServiceByBinding(b->c_str());
+            if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily()))
+                ACS = nullptr;
+        }
+        */
         if (!ACS)
             ACS = app.getDefaultAssertionConsumerService();
     }
index fb31ccf..dd9c294 100644 (file)
@@ -168,6 +168,7 @@ namespace {
         const SessionInitiator* getSessionInitiatorById(const char* id) const;
         const Handler* getDefaultAssertionConsumerService() const;
         const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;
+        const Handler* getAssertionConsumerServiceByBinding(const char* binding) const;
         const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;
         const Handler* getHandler(const char* path) const;
         void getHandlers(vector<const Handler*>& handlers) const;
@@ -224,7 +225,7 @@ namespace {
         const Handler* m_acsDefault;
 
         // maps binding strings to supporting consumer service(s)
-        typedef map<xstring,vector<const Handler*> > ACSBindingMap;
+        typedef map< string,vector<const Handler*> > ACSBindingMap;
         ACSBindingMap m_acsBindingMap;
 
         // pointer to default session initiator
@@ -647,8 +648,8 @@ XMLApplication::XMLApplication(
                         continue;
                     }
                     handler = conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), make_pair(child, getId()));
-                    // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)
-                    m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+                    // Map by binding (may be > 1 per binding)
+                    m_acsBindingMap[bindprop].push_back(handler);
                     m_acsIndexMap[handler->getUnsignedInt("index").second] = handler;
 
                     if (!hardACS) {
@@ -967,8 +968,9 @@ XMLApplication::XMLApplication(
                 string addr=string(getId()) + "::getHeaders::Application";
                 listener->regListener(addr.c_str(),this);
             }
-            else
+            else {
                 log.info("no ListenerService available, Application remoting disabled");
+            }
         }
     }
     catch (exception&) {
@@ -1212,14 +1214,22 @@ const Handler* XMLApplication::getDefaultAssertionConsumerService() const
 const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const
 {
     map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
-    if (i!=m_acsIndexMap.end()) return i->second;
+    if (i != m_acsIndexMap.end()) return i->second;
     return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : nullptr;
 }
 
-const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
+const Handler* XMLApplication::getAssertionConsumerServiceByBinding(const char* binding) const
 {
     ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
-    if (i!=m_acsBindingMap.end())
+    if (i != m_acsBindingMap.end()) return i->second.front();
+    return m_base ? m_base->getAssertionConsumerServiceByBinding(binding) : nullptr;
+}
+
+const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
+{
+    auto_ptr_char b(binding);
+    ACSBindingMap::const_iterator i=m_acsBindingMap.find(b.get());
+    if (i != m_acsBindingMap.end())
         return i->second;
     return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
 }
index f885d42..51acf69 100644 (file)
   <ItemGroup>\r
     <ClCompile Include="AbstractSPRequest.cpp" />\r
     <ClCompile Include="Application.cpp" />\r
+    <ClCompile Include="handler\impl\LogoutInitiator.cpp" />\r
     <ClCompile Include="ServiceProvider.cpp" />\r
     <ClCompile Include="SPConfig.cpp" />\r
     <ClCompile Include="util\CGIParser.cpp" />\r
     <ClCompile Include="lite\SAMLConstants.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="handler\LogoutInitiator.h" />\r
     <ClInclude Include="remoting\impl\SocketListener.h" />\r
     <ClInclude Include="AbstractSPRequest.h" />\r
     <ClInclude Include="AccessControl.h" />\r
index 4b98a41..1b75218 100644 (file)
     <ClCompile Include="lite\SAMLConstants.cpp">\r
       <Filter>Source Files\lite</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="handler\impl\LogoutInitiator.cpp">\r
+      <Filter>Source Files\handler\impl</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="remoting\impl\SocketListener.h">\r
     <ClInclude Include="lite\SAMLConstants.h">\r
       <Filter>Header Files\lite</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="handler\LogoutInitiator.h">\r
+      <Filter>Header Files\handler</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ResourceCompile Include="shibsp.rc">\r
index c8906f5..03e747d 100644 (file)
   <ItemGroup>\r
     <ClCompile Include="AbstractSPRequest.cpp" />\r
     <ClCompile Include="Application.cpp" />\r
+    <ClCompile Include="handler\impl\LogoutInitiator.cpp" />\r
     <ClCompile Include="impl\XMLSecurityPolicyProvider.cpp" />\r
     <ClCompile Include="ServiceProvider.cpp" />\r
     <ClCompile Include="SPConfig.cpp" />\r
     <ClCompile Include="handler\impl\WAYFSessionInitiator.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="handler\LogoutInitiator.h" />\r
     <ClInclude Include="remoting\impl\SocketListener.h" />\r
     <ClInclude Include="AbstractSPRequest.h" />\r
     <ClInclude Include="AccessControl.h" />\r
index 47af548..696d2e7 100644 (file)
     <ClCompile Include="impl\XMLSecurityPolicyProvider.cpp">\r
       <Filter>Source Files\impl</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="handler\impl\LogoutInitiator.cpp">\r
+      <Filter>Source Files\handler\impl</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="remoting\impl\SocketListener.h">\r
     <ClInclude Include="security\SecurityPolicyProvider.h">\r
       <Filter>Header Files\security</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="handler\LogoutInitiator.h">\r
+      <Filter>Header Files\handler</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ResourceCompile Include="shibsp.rc">\r