[cpp-sp] branch main updated: Adjustments to response URL handling.

Scott Cantor cantor.2 at osu.edu
Mon Feb 10 21:38:51 UTC 2025


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

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

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=dba93a4d806f9c033cc6658d7a8414ed79c5423a

The following commit(s) were added to refs/heads/main by this push:
     new dba93a4d Adjustments to response URL handling.
dba93a4d is described below

commit dba93a4d806f9c033cc6658d7a8414ed79c5423a
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Feb 10 16:38:47 2025 -0500

    Adjustments to response URL handling.
---
 configs/handlers.ini                               |  8 ++-
 shibsp/Makefile.am                                 |  5 +-
 shibsp/handler/HandlerConfiguration.h              | 11 +++-
 shibsp/handler/impl/AbstractHandler.cpp            |  8 ++-
 .../handler/impl/DefaultHandlerConfiguration.cpp   | 39 ++++++++++---
 shibsp/handler/impl/SessionInitiator.cpp           | 20 ++++---
 shibsp/handler/impl/TokenConsumer.cpp              | 64 ++++++++++++++++++++++
 shibsp/remoting/ddf.h                              |  3 +-
 8 files changed, 132 insertions(+), 26 deletions(-)

diff --git a/configs/handlers.ini b/configs/handlers.ini
index 606fc329..3a972f4e 100644
--- a/configs/handlers.ini
+++ b/configs/handlers.ini
@@ -1,4 +1,10 @@
-[/Status]
+[Status]
 type = Status
 acl = 127.0.0.1 ::1
 
+[Login]
+type = SessionInitiator
+
+[Validate]
+type = TokenConsumer
+
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index 6e2327c8..b868e719 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -48,8 +48,7 @@ handinclude_HEADERS = \
 	handler/LogoutHandler.h \
 	handler/LogoutInitiator.h \
 	handler/RemotedHandler.h \
-	handler/SecuredHandler.h \
-	handler/SessionInitiator.h
+	handler/SecuredHandler.h
 
 ioinclude_HEADERS = \
 	io/GenericRequest.h \
@@ -105,7 +104,6 @@ libshibsp_la_SOURCES = \
 	attribute/ScopedAttribute.cpp \
 	handler/impl/AbstractHandler.cpp \
 	handler/impl/AdminLogoutInitiator.cpp \
-	handler/impl/AssertionConsumerService.cpp \
 	handler/impl/AttributeCheckerHandler.cpp \
 	handler/impl/LocalLogoutInitiator.cpp \
 	handler/impl/DefaultHandlerConfiguration.cpp \
@@ -117,6 +115,7 @@ libshibsp_la_SOURCES = \
 	handler/impl/SessionHandler.cpp \
 	handler/impl/SessionInitiator.cpp \
 	handler/impl/StatusHandler.cpp \
+	handler/impl/TokenConsumer.cpp \
 	impl/AgentConfig.cpp \
 	impl/DefaultAgent.cpp \
 	impl/ChainingAccessControl.cpp \
diff --git a/shibsp/handler/HandlerConfiguration.h b/shibsp/handler/HandlerConfiguration.h
index 3f475757..f6bc32a4 100644
--- a/shibsp/handler/HandlerConfiguration.h
+++ b/shibsp/handler/HandlerConfiguration.h
@@ -63,7 +63,9 @@ namespace shibsp {
         virtual const Handler& getSessionInitiator() const=0;
 
         /**
-         * Gets a DDF object suitable for copying into session initiator requests to the hub.
+         * Gets a DDF object suitable for adding into session initiator requests to the hub.
+         * 
+         * <p>This is a newly allocated list that must be freed by the caller.</p>
          * 
          * <p>This is required to support the communication of the possible response
          * paths for the agent to the hub when formulating SSO protocol requests, and encapsulates
@@ -76,9 +78,12 @@ namespace shibsp {
          * "meta-informatin" required to support this legacy practice will be embedded within
          * the structure returned.</p>
          * 
-         * @return DDF object encapsulating token consumer handler metadata
+         * @param handlerURL the handler base URL with which to prefix the token consumer
+         *  endpoint paths
+         * 
+         * @return new DDF object encapsulating token consumer handler metadata
          */
-        virtual const DDF& getTokenConsumerInfo() const=0;
+        virtual DDF getTokenConsumerInfo(const char* handlerURL=nullptr) const=0;
 
         /**
          * Create a new HandlerConfiguration based on the supplied configuration file.
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 75b79ee2..1c8850e5 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -52,7 +52,6 @@ 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 StatusHandlerFactory;
     //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionHandlerFactory;
 
     //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory AdminLogoutInitiatorFactory;
@@ -60,6 +59,9 @@ namespace shibsp {
     //extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory LocalLogoutInitiatorFactory;
 
     extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory SessionInitiatorFactory;
+    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory StatusHandlerFactory;
+    extern SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<ptree&,const char*> >::Factory TokenConsumerFactory;
+
 
     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'};
@@ -88,8 +90,6 @@ void SHIBSP_API shibsp::registerHandlers()
 
     //conf.HandlerManager.registerFactory(SAML20_ASSERTION_CONSUMER_SERVICE, SAML2ConsumerFactory);
  
-    conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
-
     //conf.HandlerManager.registerFactory(SAML20_LOGOUT_HANDLER, SAML2LogoutFactory);
 
     //conf.HandlerManager.registerFactory(ADMIN_LOGOUT_INITIATOR, AdminLogoutInitiatorFactory);
@@ -97,6 +97,8 @@ void SHIBSP_API shibsp::registerHandlers()
     //conf.HandlerManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
 
     conf.HandlerManager.registerFactory(SESSION_INITIATOR_HANDLER, SessionInitiatorFactory);
+    conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
+    conf.HandlerManager.registerFactory(TOKEN_CONSUMER_HANDLER, TokenConsumerFactory);
 } 
 
 Handler::Handler()
diff --git a/shibsp/handler/impl/DefaultHandlerConfiguration.cpp b/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
index c0a7b524..233db510 100644
--- a/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
+++ b/shibsp/handler/impl/DefaultHandlerConfiguration.cpp
@@ -48,7 +48,7 @@ namespace {
 
         const Handler* getHandler(const char* path) const;
         const Handler& getSessionInitiator() const;
-        const DDF& getTokenConsumerInfo() const;
+        DDF getTokenConsumerInfo(const char* handlerURL=nullptr) const;
 
     private:
         ptree m_pt;
@@ -83,14 +83,19 @@ DefaultHandlerConfiguration::DefaultHandlerConfiguration(const char* pathname)
             throw ConfigurationException("Multiple SessionInitiator handlers were configured, only one is permitted.");
         }
 
+        string handlerPath(child.first);
+        if (handlerPath.front() != '/') {
+            handlerPath = '/' + handlerPath;
+        }
+
         // Handlers have to know their own path in some cases, so that has to be injected into the
         // factory method, as ptrees don't know their own name unfortunately, thus the section header
         // value is lost when passing the section tree itself in.
         unique_ptr<Handler> handler(AgentConfig::getConfig().HandlerManager.newPlugin(
-            type.get(), pair<ptree&,const char*>(child.second, child.first.c_str()), false));
+            type.get(), pair<ptree&,const char*>(child.second, handlerPath.c_str()), false));
             
-        m_handlerMap[child.first] = std::move(handler);
-        log.info("config (%s) installed %s handler at %s", pathname, type.get().c_str(), child.first.c_str());
+        m_handlerMap[handlerPath] = std::move(handler);
+        log.info("config (%s) installed %s handler at %s", pathname, type.get().c_str(), handlerPath.c_str());
 
         // Save off a single SessionInitiator.
         if (*type == SESSION_INITIATOR_HANDLER) {
@@ -98,7 +103,7 @@ DefaultHandlerConfiguration::DefaultHandlerConfiguration(const char* pathname)
         } else if (*type == TOKEN_CONSUMER_HANDLER) {
             DDF tokenConsumer(nullptr);
             // String value of DDF is the handler location.
-            tokenConsumer.string(child.first.c_str());
+            tokenConsumer.string(handlerPath.c_str());
             m_tokenConsumerConfig.add(tokenConsumer);
 
             // Check for legacy "binding" value to carry along with path as the name of the node.
@@ -108,6 +113,14 @@ DefaultHandlerConfiguration::DefaultHandlerConfiguration(const char* pathname)
             }
         }
     }
+
+    // If a single token consumer with no binding label is installed, convert list to unnamed string.
+    if (m_tokenConsumerConfig.integer() == 1 && !m_tokenConsumerConfig.first().name()) {
+        DDF singleEndpoint)nullptr);
+        singleEndpoint.string(m_tokenConsumerConfig.first().string());
+        m_tokenConsumerConfig.destroy();
+        m_tokenConsumerConfig = singleEndpoint;
+    }
 }
 
 const Handler* DefaultHandlerConfiguration::getHandler(const char* path) const
@@ -129,9 +142,21 @@ const Handler& DefaultHandlerConfiguration::getSessionInitiator() const
     throw runtime_error("No SessionInitiator configured?");
 }
 
-const DDF& DefaultHandlerConfiguration::getTokenConsumerInfo() const
+DDF DefaultHandlerConfiguration::getTokenConsumerInfo(const char* handlerURL) const
 {
-    return m_tokenConsumerConfig;
+    DDF dup = m_tokenConsumerConfig.copy();
+
+    if (handlerURL) {
+        DDF endpoint = dup.first();
+        while (!endpoint.isnull()) {
+            string path(handlerURL);
+            path += endpoint.string();
+            endpoint.string(path.c_str());
+            endpoint = dup.next();
+        }
+    }
+
+    return dup;
 }
 
 unique_ptr<HandlerConfiguration> HandlerConfiguration::newHandlerConfiguration(const char* pathname)
diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp
index cbd4f72f..2be3b6f5 100644
--- a/shibsp/handler/impl/SessionInitiator.cpp
+++ b/shibsp/handler/impl/SessionInitiator.cpp
@@ -91,6 +91,7 @@ pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
 {
     try {
         string state, target, handler;
+        const char* handlerBaseURL = nullptr;
 
         if (isHandler) {
             // Check for a state parameter in the query string.
@@ -100,13 +101,15 @@ pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
                 state = param;
                 // handler can be derived from "this" URL since this is a re-entrant call to this handler,
                 // i.e., we know this is the right URL to use because "it already was" originally.
-                handler = request.getHandlerURL(request.getRequestURL()) + m_path;
+                handlerBaseURL = request.getHandlerURL(request.getRequestURL());
+                handler = handlerBaseURL + m_path;
             }
             else {
                 // target will come from query string, map, or handler or fall back to this request.
                 target = getString("target", request, request.getRequestURL());
                 // handler is derived from the target resource.
-                handler = request.getHandlerURL(target.c_str()) + m_path;
+                handlerBaseURL = request.getHandlerURL(target.c_str());
+                handler = handlerBaseURL + m_path;
             }
         }
         else {
@@ -115,7 +118,8 @@ pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
                 HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP);
             // state is empty since this is a direct resource request.
             // handler is derived from the target resource
-            handler = request.getHandlerURL(target.c_str()) + m_path;
+            handlerBaseURL = request.getHandlerURL(target.c_str());
+            handler = handlerBaseURL + m_path;
         }
 
         const PropertySet* settings = request.getRequestSettings().first;
@@ -133,14 +137,14 @@ pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
             input.addmember("state").string(state.c_str());
         }
 
-        const DDF& consumers = request.getAgent().getHandlerConfiguration(
-            settings->getString("handlerConfigID")).getTokenConsumerInfo();
-        DDF dup = consumers.copy();
+        // Add copy of token consumer structure.
+        DDF dup = request.getAgent().getHandlerConfiguration(
+            settings->getString("handlerConfigID")).getTokenConsumerInfo(handlerBaseURL);
         input.add(dup);
 
         DDF wrapped = wrapRequest(request, m_remotedHeaders,
-            !isHandler && getBool("preservePostData", request, false,
-                HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP));
+            !isHandler &&
+                getBool("preservePostData", request, false, HANDLER_PROPERTY_FIXED | HANDLER_PROPERTY_MAP));
         input.add(wrapped);
 
         for (const string& propname : m_requestMapperSettings) {
diff --git a/shibsp/handler/impl/TokenConsumer.cpp b/shibsp/handler/impl/TokenConsumer.cpp
new file mode 100644
index 00000000..34f5d9f1
--- /dev/null
+++ b/shibsp/handler/impl/TokenConsumer.cpp
@@ -0,0 +1,64 @@
+/**
+ * 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/TokenCOnsumer.cpp
+ *
+ * SSO protocol response handler.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "SPRequest.h"
+#include "handler/AbstractHandler.h"
+#include "logging/Category.h"
+
+#include <ctime>
+#include <boost/property_tree/ptree.hpp>
+
+using namespace shibsp;
+using namespace boost::property_tree;
+using namespace std;
+
+namespace {
+    class SHIBSP_DLLLOCAL TokenConsumer : public virtual AbstractHandler {
+    public:
+        TokenConsumer(const ptree& pt, const char* path);
+        virtual ~TokenConsumer() {}
+
+        pair<bool,long> run(SPRequest& request, bool isHandler) const;
+
+    private:
+        string m_path;
+        vector<string> m_remotedHeaders;
+    };
+};
+
+namespace shibsp {
+    Handler* SHIBSP_DLLLOCAL TokenConsumerFactory(const pair<ptree&,const char*>& p, bool) {
+        return new TokenConsumer(p.first, p.second);
+    }
+};
+
+TokenConsumer::TokenConsumer(const ptree& pt, const char* path)
+    : AbstractHandler(pt, Category::getInstance(SHIBSP_LOGCAT ".Handler.TokenConsumer")),
+        m_path(path), m_remotedHeaders({ "Cookie" })
+{
+
+}
+
+pair<bool,long> TokenConsumer::run(SPRequest& request, bool isHandler) const
+{
+    return make_pair(false, 0);
+}
diff --git a/shibsp/remoting/ddf.h b/shibsp/remoting/ddf.h
index 7bc1e914..ed1f25c8 100644
--- a/shibsp/remoting/ddf.h
+++ b/shibsp/remoting/ddf.h
@@ -55,7 +55,8 @@ namespace shibsp {
         DDF copy() const;       // deep copy routine
     
         // property accessors
-        const char* name() const;           DDF& name(const char* n);
+        const char* name() const;
+        DDF& name(const char* n);
     
         // basic type checking
         bool isnull() const;

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


More information about the commits mailing list