Factor entityID into SessionInitiator subinterface, move WAYF logic out of Shib handler.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Wed, 4 Apr 2007 21:12:47 +0000 (21:12 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Wed, 4 Apr 2007 21:12:47 +0000 (21:12 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2216 cb58f699-b61c-0410-a6fe-9272a202ed29

15 files changed:
configs/shibboleth.xml.in
schemas/shibboleth-spconfig-2.0.xsd
shibsp/Application.h
shibsp/Makefile.am
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/ServiceProvider.cpp
shibsp/handler/Handler.h
shibsp/handler/SessionInitiator.h [new file with mode: 0644]
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/ChainingSessionInitiator.cpp
shibsp/handler/impl/SessionInitiator.cpp [new file with mode: 0644]
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/impl/XMLServiceProvider.cpp
shibsp/shibsp.vcproj

index 6f07abf..eb59317 100644 (file)
                        element (or requireSessionWith can specify a specific id to use). Lazy sessions
                        can be started with any initiator by redirecting to it using query string parameters:
                        
-                        *  entityID    optional direct invocation of a specific IdP
-                        *  target      optional resource to direct back to later (or homeURL will be used)
-                        *  acsIndex    optional index of an ACS to use on the way back in
+                        * entityID                             optional direct invocation of a specific IdP
+                        * target                               optional resource to direct back to later (or homeURL will be used)
+                        * acsIndex                             optional index of an ACS to use on the way back in
+                        
+                       The following options can be set against content in the RequestMap or supplied on a query string
+                       to override default or AuthnRequest template content when using SAML 2.0. They will be ignored
+                       if the outgoing SSO protocol doesn't support them.
+                       
+                        * forceAuthn                           insist on user reauthentication at IdP
+                        * isPassive                            preclude interaction at IdP or discovery service
+                        * authnContextClassRef         URI reference of an AuthnContextClass to request
+                        * authnContextDeclRef          URI reference of an AuthnContextDecl to request
+                        * authnContextComparison       comparison operator to apply to AuthnContext reference 
                        -->
 
-                       <!-- Default example directs to a specific IdP's Shibboleth 1.x SSO service. -->
-                       <SessionInitiator type="Shibboleth" Location="/Login" isDefault="true" id="example.org"
-                               relayState="cookie" entityID="https://idp.example.org/shibboleth"/>
+                       <!-- Default example directs to a specific IdP's SSO service (favoring SAML 2 over Shib 1). -->
+                       <SessionInitiator type="Chaining" Location="/Login" isDefault="true" id="example.org"
+                                       relayState="cookie" entityID="https://idp.example.org/shibboleth">
+                               <SessionInitiator type="SAML2"/>
+                               <SessionInitiator type="Shibboleth"/>
+                       </SessionInitiator>
+                       
+                       <!-- An example using an old-style WAYF, which means Shib 1 only unless an entityID is provided. -->
+                       <SessionInitiator type="Chaining" Location="/WAYF" id="WAYF" relayState="cookie">
+                               <SessionInitiator type="SAML2"/>
+                               <SessionInitiator type="Shibboleth"/>
+                               <SessionInitiator type="WAYF" URL="https://wayf.example.org/WAYF"/>
+                       </SessionInitiator>
+
+                       <!-- An example supporting the new-style of discovery service. -->
+                       <SessionInitiator type="Chaining" Location="/DS" id="DS" relayState="cookie">
+                               <SessionInitiator type="SAML2"/>
+                               <SessionInitiator type="Shibboleth"/>
+                               <SessionInitiator type="SAMLDS" URL="https://ds.example.org/DS"/>
+                       </SessionInitiator>
                        
-                       <!-- An example using the Shibboleth 1.x protocol but with an external WAYF. -->
-                       <SessionInitiator type="Shibboleth" Location="/WAYF" id="wayf"
-                               relayState="cookie" wayfURL="https://wayf.example.org/WAYF"/>
-                               
                        <!--
                        md:AssertionConsumerService elements handle specific SSO protocol bindings,
                        such as SAML 2.0 POST or SAML 1.1 Artifact. The isDefault and index attributes
index 5d222f1..adab6b1 100644 (file)
                <attribute name="requireSessionWith" type="conf:string"/>\r
                <attribute name="exportAssertion" type="boolean"/>\r
                <attribute name="redirectToSSL" type="unsignedInt"/>\r
+               <attribute name="isPassive" type="boolean"/>\r
+               <attribute name="forceAuthn" type="boolean"/>\r
+               <attribute name="authnContextClassRef" type="anyURI"/>\r
+               <attribute name="authnContextDeclRef" type="anyURI"/>\r
+               <attribute name="authnContextComparison" type="conf:string"/>\r
                <anyAttribute namespace="##other" processContents="lax"/>\r
        </attributeGroup>\r
        <element name="AccessControlProvider" type="conf:PluggableType"/>\r
                                        <attribute name="Location" type="anyURI"/>\r
                                        <attribute name="id" type="conf:string"/>\r
                                        <attribute name="isDefault" type="boolean"/>\r
-                                       <attribute name="wayfURL" type="anyURI"/>\r
                                        <attribute name="relayState" type="conf:string"/>\r
+                                       <attribute name="entityIDParam" type="conf:string"/>\r
                                        <attribute name="entityID" type="anyURI"/>\r
+                                       <attribute name="URL" type="anyURI"/>\r
                                        <anyAttribute namespace="##any" processContents="lax"/>\r
                                </restriction>\r
                        </complexContent>\r
index 4b42220..f4ca169 100644 (file)
@@ -33,6 +33,7 @@ namespace shibsp {
     class SHIBSP_API AttributeResolver;
     class SHIBSP_API Handler;
     class SHIBSP_API ServiceProvider;
+    class SHIBSP_API SessionInitiator;
 
     /**
      * Interface to a Shibboleth Application instance.
@@ -121,21 +122,19 @@ namespace shibsp {
         virtual const PropertySet* getRelyingParty(const opensaml::saml2md::EntityDescriptor* provider) const=0;
 
         /**
-         * Returns the default SessionInitiator Handler when automatically
-         * requesting a session.
+         * Returns the default SessionInitiator when automatically requesting a session.
          * 
          * @return the default SessionInitiator, or NULL
          */
-        virtual const Handler* getDefaultSessionInitiator() const=0;
+        virtual const SessionInitiator* getDefaultSessionInitiator() const=0;
         
         /**
-         * Returns a SessionInitiator Handler with a particular ID when automatically
-         * requesting a session.
+         * Returns a SessionInitiator with a particular ID when automatically requesting a session.
          * 
          * @param id    an identifier unique to the Application
          * @return the designated SessionInitiator, or NULL
          */
-        virtual const Handler* getSessionInitiatorById(const char* id) const=0;
+        virtual const SessionInitiator* getSessionInitiatorById(const char* id) const=0;
         
         /**
          * Returns the default AssertionConsumerService Handler
index b3045c6..1683d89 100644 (file)
@@ -57,7 +57,8 @@ handinclude_HEADERS = \
        handler/AbstractHandler.h \
        handler/AssertionConsumerService.h \
        handler/Handler.h \
-       handler/RemotedHandler.h
+       handler/RemotedHandler.h \
+       handler/SessionInitiator.h
 
 mdinclude_HEADERS = \
        metadata/MetadataExt.h
@@ -100,6 +101,7 @@ libshibsp_la_SOURCES = \
        handler/impl/RemotedHandler.cpp \
        handler/impl/SAML1Consumer.cpp \
        handler/impl/SAML2Consumer.cpp \
+       handler/impl/SessionInitiator.cpp \
        handler/impl/Shib1SessionInitiator.cpp \
        impl/RemotedSessionCache.cpp \
        impl/StorageServiceSessionCache.cpp \
index 3b6940a..1de2dd4 100644 (file)
@@ -31,7 +31,7 @@
 #include "attribute/AttributeDecoder.h"
 #include "attribute/resolver/AttributeResolver.h"
 #include "binding/ArtifactResolver.h"
-#include "handler/Handler.h"
+#include "handler/SessionInitiator.h"
 #include "metadata/MetadataExt.h"
 #include "remoting/ListenerService.h"
 #include "security/PKIXTrustEngine.h"
@@ -111,6 +111,7 @@ bool SPInternalConfig::init(const char* catalog_path)
     registerAttributeFactories();
     registerAttributeResolvers();
     registerHandlers();
+    registerSessionInitiators();
     registerListenerServices();
     registerRequestMappers();
     registerSessionCaches();
index dfcd19c..f56dd9f 100644 (file)
@@ -42,6 +42,7 @@ namespace shibsp {
     class SHIBSP_API RequestMapper;
     class SHIBSP_API ServiceProvider;
     class SHIBSP_API SessionCache;
+    class SHIBSP_API SessionInitiator;
 
 #if defined (_MSC_VER)
     #pragma warning( push )
@@ -214,7 +215,7 @@ namespace shibsp {
         /**
          * Manages factories for Handler plugins that implement SessionInitiator functionality.
          */
-        xmltooling::PluginManager< Handler,std::pair<const xercesc::DOMElement*,const char*> > SessionInitiatorManager;
+        xmltooling::PluginManager< SessionInitiator,std::pair<const xercesc::DOMElement*,const char*> > SessionInitiatorManager;
 
         /**
          * Manages factories for Handler plugins that implement SingleLogoutService functionality.
index a9fd473..01e2ce9 100644 (file)
@@ -28,7 +28,7 @@
 #include "SessionCache.h"
 #include "SPRequest.h"
 #include "attribute/Attribute.h"
-#include "handler/Handler.h"
+#include "handler/SessionInitiator.h"
 #include "util/TemplateParameters.h"
 
 #include <fstream>
index 2103d34..0517af9 100644 (file)
@@ -59,7 +59,7 @@ namespace shibsp {
     /** SessionInitiator that iterates through a set of protocol-specific versions. */
     #define CHAINING_SESSION_INITIATOR "Chaining"
 
-    /** SessionInitiator that supports Shibboleth V1 AuthnRequest/WAYF redirects. */
+    /** SessionInitiator that supports Shibboleth V1 AuthnRequest redirects. */
     #define SHIB1_SESSION_INITIATOR "Shibboleth"
 };
 
diff --git a/shibsp/handler/SessionInitiator.h b/shibsp/handler/SessionInitiator.h
new file mode 100644 (file)
index 0000000..da9d196
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  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.
+ * 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/SessionInitiator.h
+ * 
+ * Pluggable runtime functionality that handles initiating sessions.
+ */
+
+#ifndef __shibsp_initiator_h__
+#define __shibsp_initiator_h__
+
+#include <shibsp/handler/Handler.h>
+
+namespace shibsp {
+
+    /**
+     * Pluggable runtime functionality that handles initiating sessions.
+     *
+     * <p>By default, SessionInitiators look for an entityID on the incoming request
+     * and pass control to the specialized run method.
+     */
+    class SHIBSP_API SessionInitiator : public virtual Handler
+    {
+    protected:
+        SessionInitiator() {}
+
+    public:
+        virtual ~SessionInitiator() {}
+
+        /**
+         * Executes an incoming request.
+         * 
+         * <p>SessionInitiators can be run either directly by incoming web requests
+         * or indirectly/implicitly during other SP processing.
+         * 
+         * @param request   SP request context
+         * @param entityID  the name of an IdP to request a session from, if known
+         * @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, const char* entityID=NULL, bool isHandler=true) const=0;
+
+        std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
+    };
+    
+    /** Registers SessionInitiator implementations. */
+    void SHIBSP_API registerSessionInitiators();
+
+    /** SessionInitiator that iterates through a set of protocol-specific versions. */
+    #define CHAINING_SESSION_INITIATOR "Chaining"
+
+    /** SessionInitiator that supports SAML 2.0 AuthnRequests. */
+    #define SAML2_SESSION_INITIATOR "SAML2"
+
+    /** SessionInitiator that supports SAML Discovery Service protocol. */
+    #define SAMLDS_SESSION_INITIATOR "SAMLDS"
+
+    /** SessionInitiator that supports Shibboleth V1 AuthnRequest redirects. */
+    #define SHIB1_SESSION_INITIATOR "Shibboleth"
+
+    /** SessionInitiator that supports Shibboleth V1 WAYF redirects when no IdP is supplied. */
+    #define WAYF_SESSION_INITIATOR "WAYF"
+};
+
+#endif /* __shibsp_initiator_h__ */
index 9048453..3247a00 100644 (file)
@@ -47,8 +47,6 @@ using namespace std;
 namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager<Handler,pair<const DOMElement*,const char*>>::Factory SAML1ConsumerFactory;
     SHIBSP_DLLLOCAL PluginManager<Handler,pair<const DOMElement*,const char*>>::Factory SAML2ConsumerFactory;
-    SHIBSP_DLLLOCAL PluginManager<Handler,pair<const DOMElement*,const char*>>::Factory ChainingSessionInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager<Handler,pair<const DOMElement*,const char*>>::Factory Shib1SessionInitiatorFactory;
 };
 
 void SHIBSP_API shibsp::registerHandlers()
@@ -60,9 +58,6 @@ void SHIBSP_API shibsp::registerHandlers()
     conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);
     conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);
     conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);
-
-    conf.SessionInitiatorManager.registerFactory(CHAINING_SESSION_INITIATOR, ChainingSessionInitiatorFactory);
-    conf.SessionInitiatorManager.registerFactory(SHIB1_SESSION_INITIATOR, Shib1SessionInitiatorFactory);
 }
 
 AbstractHandler::AbstractHandler(
index df52c08..38bad77 100644 (file)
@@ -23,6 +23,7 @@
 #include "internal.h"
 #include "exceptions.h"
 #include "handler/AbstractHandler.h"
+#include "handler/SessionInitiator.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -40,43 +41,43 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class SHIBSP_DLLLOCAL ChainingSessionInitiator : public AbstractHandler
+    class SHIBSP_DLLLOCAL ChainingSessionInitiator : public SessionInitiator, public AbstractHandler
     {
     public:
         ChainingSessionInitiator(const DOMElement* e, const char* appId);
         virtual ~ChainingSessionInitiator() {
-            for_each(m_handlers.begin(), m_handlers.end(), xmltooling::cleanup<Handler>());
+            for_each(m_handlers.begin(), m_handlers.end(), xmltooling::cleanup<SessionInitiator>());
         }
         
-        pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
+        pair<bool,long> run(SPRequest& request, const char* entityID=NULL, bool isHandler=true) const;
 
     private:
-        vector<Handler*> m_handlers;
+        vector<SessionInitiator*> m_handlers;
     };
 
 #if defined (_MSC_VER)
     #pragma warning( pop )
 #endif
 
-    Handler* SHIBSP_DLLLOCAL ChainingSessionInitiatorFactory(const pair<const DOMElement*,const char*>& p)
-    {
-        return new ChainingSessionInitiator(p.first, p.second);
-    }
-
-    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 _type[] =            UNICODE_LITERAL_4(t,y,p,e);
+    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 _type[] =                UNICODE_LITERAL_4(t,y,p,e);
 
     class SHIBSP_DLLLOCAL SessionInitiatorNodeFilter : public DOMNodeFilter
     {
     public:
         short acceptNode(const DOMNode* node) const {
-            if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,SessionInitiator))
+            if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,_SessionInitiator))
                 return FILTER_REJECT;
             return FILTER_ACCEPT;
         }
     };
 
     static SHIBSP_DLLLOCAL SessionInitiatorNodeFilter g_SINFilter;
+
+    SessionInitiator* SHIBSP_DLLLOCAL ChainingSessionInitiatorFactory(const pair<const DOMElement*,const char*>& p)
+    {
+        return new ChainingSessionInitiator(p.first, p.second);
+    }
 };
 
 ChainingSessionInitiator::ChainingSessionInitiator(const DOMElement* e, const char* appId)
@@ -85,22 +86,27 @@ ChainingSessionInitiator::ChainingSessionInitiator(const DOMElement* e, const ch
     SPConfig& conf = SPConfig::getConfig();
 
     // Load up the chain of handlers.
-    e = e ? XMLHelper::getFirstChildElement(e, SessionInitiator) : NULL;
+    e = e ? XMLHelper::getFirstChildElement(e, _SessionInitiator) : NULL;
     while (e) {
         auto_ptr_char type(e->getAttributeNS(NULL,_type));
         if (type.get() && *(type.get())) {
-            m_handlers.push_back(conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(e, appId)));
-            m_handlers.back()->setParent(this);
+            try {
+                m_handlers.push_back(conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(e, appId)));
+                m_handlers.back()->setParent(this);
+            }
+            catch (exception& ex) {
+                m_log.error("caught exception processing embedded SessionInitiator element: %s", ex.what());
+            }
         }
-        e = XMLHelper::getNextSiblingElement(e, SessionInitiator);
+        e = XMLHelper::getNextSiblingElement(e, _SessionInitiator);
     }
 }
 
-pair<bool,long> ChainingSessionInitiator::run(SPRequest& request, bool isHandler) const
+pair<bool,long> ChainingSessionInitiator::run(SPRequest& request, const char* entityID, bool isHandler) const
 {
     pair<bool,long> ret;
-    for (vector<Handler*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i) {
-        ret = (*i)->run(request, isHandler);
+    for (vector<SessionInitiator*>::const_iterator i = m_handlers.begin(); i!=m_handlers.end(); ++i) {
+        ret = (*i)->run(request, entityID, isHandler);
         if (ret.first)
             return ret;
     }
diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp
new file mode 100644 (file)
index 0000000..cb6a87d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  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.
+ * 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.
+ */
+
+/**
+ * SessionInitiator.cpp
+ * 
+ * Pluggable runtime functionality that handles initiating sessions.
+ */
+
+#include "internal.h"
+#include "SPRequest.h"
+#include "handler/SessionInitiator.h"
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    SHIBSP_DLLLOCAL PluginManager<SessionInitiator,pair<const DOMElement*,const char*>>::Factory ChainingSessionInitiatorFactory;
+    SHIBSP_DLLLOCAL PluginManager<SessionInitiator,pair<const DOMElement*,const char*>>::Factory Shib1SessionInitiatorFactory;
+};
+
+void SHIBSP_API shibsp::registerSessionInitiators()
+{
+    SPConfig& conf=SPConfig::getConfig();
+    
+    conf.SessionInitiatorManager.registerFactory(CHAINING_SESSION_INITIATOR, ChainingSessionInitiatorFactory);
+    conf.SessionInitiatorManager.registerFactory(SHIB1_SESSION_INITIATOR, Shib1SessionInitiatorFactory);
+}
+
+pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
+{
+    const char* entityID=NULL;
+    pair<bool,const char*> param = getString("entityIDParam");
+
+    if (isHandler) {
+        entityID=request.getParameter(param.first ? param.second : "entityID");
+        if (!param.first && (!entityID || !*entityID))
+            entityID=request.getParameter("providerId");
+    }
+    if (!entityID || !*entityID)
+        entityID=getString("entityID").second;
+
+    return run(request, entityID, isHandler);
+}
index aa89402..0b6d5bc 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * Shib1SessionInitiator.cpp
  * 
- * Shibboleth 1.x AuthnRequest/WAYF support.
+ * Shibboleth 1.x AuthnRequest support.
  */
 
 #include "internal.h"
@@ -25,6 +25,7 @@
 #include "exceptions.h"
 #include "SPRequest.h"
 #include "handler/AbstractHandler.h"
+#include "handler/SessionInitiator.h"
 #include "util/SPConstants.h"
 
 #include <saml/saml2/metadata/Metadata.h>
@@ -48,100 +49,83 @@ namespace shibsp {
     #pragma warning( disable : 4250 )
 #endif
 
-    class SHIBSP_DLLLOCAL Shib1SessionInitiator : public AbstractHandler
+    class SHIBSP_DLLLOCAL Shib1SessionInitiator : public SessionInitiator, public AbstractHandler
     {
     public:
         Shib1SessionInitiator(const DOMElement* e, const char* appId)
             : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator")) {}
         virtual ~Shib1SessionInitiator() {}
         
-        pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
-    private:
-        pair<bool,long> doAuthnRequest(SPRequest& request, const Handler* shire, const char* dest, string& target) const;
+        pair<bool,long> run(SPRequest& request, const char* entityID=NULL, bool isHandler=true) const;
     };
 
 #if defined (_MSC_VER)
     #pragma warning( pop )
 #endif
 
-    Handler* SHIBSP_DLLLOCAL Shib1SessionInitiatorFactory(const pair<const DOMElement*,const char*>& p)
+    SessionInitiator* SHIBSP_DLLLOCAL Shib1SessionInitiatorFactory(const pair<const DOMElement*,const char*>& p)
     {
         return new Shib1SessionInitiator(p.first, p.second);
     }
 
 };
 
-pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, bool isHandler) const
+pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, const char* entityID, bool isHandler) const
 {
+    // We have to know the IdP to function.
+    if (!entityID || !*entityID)
+        return make_pair(false,0);
+
     string target;
-    const char* entityID=NULL;
     const Handler* ACS=NULL;
     const Application& app=request.getApplication();
-    
+
     if (isHandler) {
-        entityID=request.getParameter("acsIndex");
-        if (entityID)
-            ACS=app.getAssertionConsumerServiceByIndex(atoi(entityID));
+        const char* option=request.getParameter("acsIndex");
+        if (option)
+            ACS=app.getAssertionConsumerServiceByIndex(atoi(option));
 
-        entityID = request.getParameter("target");
-        if (entityID)
-            target = entityID;
+        option = request.getParameter("target");
+        if (option)
+            target = option;
         recoverRelayState(request, target);
-
-        // Try and establish which IdP to use.
-        entityID=request.getParameter("entityID");
-        if (!entityID || !*entityID)
-            entityID=request.getParameter("providerId");
-        if (!entityID || !*entityID)
-            entityID=getString("entityID").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.
-        entityID=getString("entityID").second;
         target=request.getRequestURL();
     }
         
-    if (entityID && *entityID) {
-        m_log.debug("attempting to initiate session using SAML 1.x with provider (%s)", entityID);
-
-        // Use metadata to invoke the SSO service directly.
-        MetadataProvider* m=app.getMetadataProvider();
-        Locker locker(m);
-        const EntityDescriptor* entity=m->getEntityDescriptor(entityID);
-        if (!entity) {
-            m_log.error("unable to locate metadata for provider (%s)", entityID);
-            return make_pair(false,0);
-        }
-        const IDPSSODescriptor* role=entity->getIDPSSODescriptor(shibspconstants::SHIB1_PROTOCOL_ENUM);
-        if (!role) {
-            m_log.error("unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
-            return make_pair(false,0);
-        }
-        const EndpointType* ep=EndpointManager<SingleSignOnService>(role->getSingleSignOnServices()).getByBinding(
-            shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI
-            );
-        if (!ep) {
-            m_log.error("unable to locate compatible SSO service for provider (%s)", entityID);
-            return make_pair(false,0);
-        }
-        auto_ptr_char dest(ep->getLocation());
-        return doAuthnRequest(request, ACS ? ACS : app.getDefaultAssertionConsumerService(), dest.get(), target);
+    m_log.debug("attempting to initiate session using SAML 1.x with provider (%s)", entityID);
+
+    // Use metadata to invoke the SSO service directly.
+    MetadataProvider* m=app.getMetadataProvider();
+    Locker locker(m);
+    const EntityDescriptor* entity=m->getEntityDescriptor(entityID);
+    if (!entity) {
+        m_log.error("unable to locate metadata for provider (%s)", entityID);
+        return make_pair(false,0);
     }
-    
-    // Fall back to optional legacy discovery service.
-    pair<bool,const char*> wayfURL=getString("wayfURL");
-    if (!wayfURL.first)
+    const IDPSSODescriptor* role=entity->getIDPSSODescriptor(shibspconstants::SHIB1_PROTOCOL_ENUM);
+    if (!role) {
+        m_log.error("unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
         return make_pair(false,0);
-    return doAuthnRequest(request, ACS ? ACS : app.getDefaultAssertionConsumerService(), wayfURL.second, target);
-}
+    }
+    const EndpointType* ep=EndpointManager<SingleSignOnService>(role->getSingleSignOnServices()).getByBinding(
+        shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI
+        );
+    if (!ep) {
+        m_log.error("unable to locate compatible SSO service for provider (%s)", entityID);
+        return make_pair(false,0);
+    }
+    auto_ptr_char dest(ep->getLocation());
+
+    if (!ACS)
+        ACS = app.getDefaultAssertionConsumerService();
 
-pair<bool,long> Shib1SessionInitiator::doAuthnRequest(SPRequest& request, const Handler* shire, const char* dest, string& target) const
-{
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
     string ACSloc=request.getHandlerURL(target.c_str());
-    pair<bool,const char*> loc=shire ? shire->getString("Location") : pair<bool,const char*>(false,NULL);
+    pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
     if (loc.first) ACSloc+=loc.second;
 
     preserveRelayState(request, target);
@@ -149,8 +133,8 @@ pair<bool,long> Shib1SessionInitiator::doAuthnRequest(SPRequest& request, const
     char timebuf[16];
     sprintf(timebuf,"%u",time(NULL));
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
-    string req=string(dest) + "?shire=" + urlenc->encode(ACSloc.c_str()) + "&time=" + timebuf + "&target=" + target +
-        "&providerId=" + urlenc->encode(request.getApplication().getString("entityID").second);
+    string req=string(dest.get()) + "?shire=" + urlenc->encode(ACSloc.c_str()) + "&time=" + timebuf + "&target=" + target +
+        "&providerId=" + urlenc->encode(app.getString("entityID").second);
 
     return make_pair(true, request.sendRedirect(req.c_str()));
 }
index 725970a..bdf5045 100644 (file)
@@ -31,7 +31,7 @@
 #include "SPRequest.h"\r
 #include "TransactionLog.h"\r
 #include "attribute/resolver/AttributeResolver.h"\r
-#include "handler/Handler.h"\r
+#include "handler/SessionInitiator.h"\r
 #include "remoting/ListenerService.h"\r
 #include "security/PKIXTrustEngine.h"\r
 #include "util/DOMPropertySet.h"\r
@@ -97,8 +97,8 @@ namespace {
         }\r
         const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;\r
 \r
-        const Handler* getDefaultSessionInitiator() const;\r
-        const Handler* getSessionInitiatorById(const char* id) const;\r
+        const SessionInitiator* getDefaultSessionInitiator() const;\r
+        const SessionInitiator* getSessionInitiatorById(const char* id) const;\r
         const Handler* getDefaultAssertionConsumerService() const;\r
         const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;\r
         const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;\r
@@ -143,11 +143,11 @@ namespace {
 #endif\r
         ACSBindingMap m_acsBindingMap;\r
 \r
-        // maps unique ID strings to session initiators\r
-        map<string,const Handler*> m_sessionInitMap;\r
-\r
         // pointer to default session initiator\r
-        const Handler* m_sessionInitDefault;\r
+        const SessionInitiator* m_sessionInitDefault;\r
+\r
+        // maps unique ID strings to session initiators\r
+        map<string,const SessionInitiator*> m_sessionInitMap;\r
 \r
         // RelyingParty properties\r
         DOMPropertySet* m_partyDefault;\r
@@ -309,7 +309,7 @@ namespace {
     static const XMLCh Rule[] =                 UNICODE_LITERAL_4(R,u,l,e);\r
     static const XMLCh SecurityPolicies[] =     UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);\r
     static const XMLCh _SessionCache[] =        UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);\r
-    static const XMLCh SessionInitiator[] =     UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
+    static const XMLCh _SessionInitiator[] =    UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
     static const XMLCh _StorageService[] =      UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);\r
     static const XMLCh TCPListener[] =          UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);\r
     static const XMLCh _TrustEngine[] =         UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);\r
@@ -417,27 +417,28 @@ XMLApplication::XMLApplication(
                             m_acsDefault=handler;\r
                     }\r
                 }\r
-                else if (XMLString::equals(child->getLocalName(),SessionInitiator)) {\r
+                else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {\r
                     auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
                     if (!type.get() || !*(type.get())) {\r
                         log.warn("SessionInitiator element has no type attribute, skipping it...");\r
                         child = XMLHelper::getNextSiblingElement(child);\r
                         continue;\r
                     }\r
-                    handler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+                    SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+                    handler=sihandler;\r
                     pair<bool,const char*> si_id=handler->getString("id");\r
                     if (si_id.first && si_id.second)\r
-                        m_sessionInitMap[si_id.second]=handler;\r
+                        m_sessionInitMap[si_id.second]=sihandler;\r
                     if (!hardSessionInit) {\r
                         pair<bool,bool> defprop=handler->getBool("isDefault");\r
                         if (defprop.first) {\r
                             if (defprop.second) {\r
                                 hardSessionInit=true;\r
-                                m_sessionInitDefault=handler;\r
+                                m_sessionInitDefault=sihandler;\r
                             }\r
                         }\r
                         else if (!m_sessionInitDefault)\r
-                            m_sessionInitDefault=handler;\r
+                            m_sessionInitDefault=sihandler;\r
                     }\r
                 }\r
                 else if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME)) {\r
@@ -610,7 +611,7 @@ short XMLApplication::acceptNode(const DOMNode* node) const
         XMLString::equals(name,AssertionConsumerService::LOCAL_NAME) ||\r
         XMLString::equals(name,SingleLogoutService::LOCAL_NAME) ||\r
         XMLString::equals(name,ManageNameIDService::LOCAL_NAME) ||\r
-        XMLString::equals(name,SessionInitiator) ||\r
+        XMLString::equals(name,_SessionInitiator) ||\r
         XMLString::equals(name,DefaultRelyingParty) ||\r
         XMLString::equals(name,RelyingParty) ||\r
         XMLString::equals(name,_MetadataProvider) ||\r
@@ -658,15 +659,15 @@ const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provi
     return m_partyDefault;\r
 }\r
 \r
-const Handler* XMLApplication::getDefaultSessionInitiator() const\r
+const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const\r
 {\r
     if (m_sessionInitDefault) return m_sessionInitDefault;\r
     return m_base ? m_base->getDefaultSessionInitiator() : NULL;\r
 }\r
 \r
-const Handler* XMLApplication::getSessionInitiatorById(const char* id) const\r
+const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const\r
 {\r
-    map<string,const Handler*>::const_iterator i=m_sessionInitMap.find(id);\r
+    map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);\r
     if (i!=m_sessionInitMap.end()) return i->second;\r
     return m_base ? m_base->getSessionInitiatorById(id) : NULL;\r
 }\r
index 81b1f08..7f7d96d 100644 (file)
                                                >\r
                                        </File>\r
                                        <File\r
+                                               RelativePath=".\handler\impl\SessionInitiator.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\handler\impl\Shib1SessionInitiator.cpp"\r
                                                >\r
                                        </File>\r
                                        RelativePath=".\handler\RemotedHandler.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\handler\SessionInitiator.h"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                </Filter>\r
                <Filter\r