[cpp-sp] branch main updated: Remove Generic request/response interfaces

Codeberg noreply at shibboleth.net
Thu Jun 4 18:45:50 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/e4cced44f76d8f4226a3c30aef52adf2389d821d

The following commit(s) were added to refs/heads/main by this push:
     new e4cced44 Remove Generic request/response interfaces
e4cced44 is described below

commit e4cced44f76d8f4226a3c30aef52adf2389d821d
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Thu Jun 4 14:45:33 2026 -0400

    Remove Generic request/response interfaces
---
 Projects/vc22/shibsp.vcxproj                    |   2 -
 Projects/vc22/shibsp.vcxproj.filters            |   6 -
 apache/mod_shib4.cpp                            |   2 +-
 fastcgi/shibauthorizer.cpp                      |   3 +-
 fastcgi/shibresponder.cpp                       |   3 +-
 iis/IIS7Request.cpp                             |   2 +-
 shibsp/AbstractSPRequest.cpp                    |  48 +++++++
 shibsp/AbstractSPRequest.h                      |  26 +++-
 shibsp/Agent.cpp                                |  22 +++-
 shibsp/Makefile.am                              |   2 -
 shibsp/handler/impl/AbstractHandler.cpp         |   6 +-
 shibsp/handler/impl/AttributeCheckerHandler.cpp |   4 +-
 shibsp/handler/impl/LogoutConsumer.cpp          |  11 +-
 shibsp/handler/impl/LogoutInitiator.cpp         |  11 +-
 shibsp/handler/impl/TokenConsumer.cpp           |   1 -
 shibsp/impl/DefaultAgent.cpp                    |   5 +-
 shibsp/io/GenericRequest.h                      | 168 ------------------------
 shibsp/io/GenericResponse.h                     |  78 -----------
 shibsp/io/HTTPRequest.h                         | 117 ++++++++++++++++-
 shibsp/io/HTTPResponse.h                        |  66 +++++-----
 shibsp/io/impl/HTTPRequest.cpp                  |  27 ----
 shibsp/io/impl/HTTPResponse.cpp                 |  48 -------
 tests/DummyRequest.h                            |   1 +
 23 files changed, 249 insertions(+), 410 deletions(-)

diff --git a/Projects/vc22/shibsp.vcxproj b/Projects/vc22/shibsp.vcxproj
index 6eac1914..4de41ef0 100644
--- a/Projects/vc22/shibsp.vcxproj
+++ b/Projects/vc22/shibsp.vcxproj
@@ -47,8 +47,6 @@
     <ClInclude Include="..\..\shibsp\handler\SecuredHandler.h" />
     <ClInclude Include="..\..\shibsp\internal.h" />
     <ClInclude Include="..\..\shibsp\io\CookieManager.h" />
-    <ClInclude Include="..\..\shibsp\io\GenericRequest.h" />
-    <ClInclude Include="..\..\shibsp\io\GenericResponse.h" />
     <ClInclude Include="..\..\shibsp\io\HTTPRequest.h" />
     <ClInclude Include="..\..\shibsp\io\HTTPResponse.h" />
     <ClInclude Include="..\..\shibsp\logging\Category.h" />
diff --git a/Projects/vc22/shibsp.vcxproj.filters b/Projects/vc22/shibsp.vcxproj.filters
index d866eac3..1227abb5 100644
--- a/Projects/vc22/shibsp.vcxproj.filters
+++ b/Projects/vc22/shibsp.vcxproj.filters
@@ -129,12 +129,6 @@
     <ClInclude Include="..\..\shibsp\io\CookieManager.h">
       <Filter>Header Files\IO</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\shibsp\io\GenericRequest.h">
-      <Filter>Header Files\IO</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\shibsp\io\GenericResponse.h">
-      <Filter>Header Files\IO</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\shibsp\io\HTTPRequest.h">
       <Filter>Header Files\IO</Filter>
     </ClInclude>
diff --git a/apache/mod_shib4.cpp b/apache/mod_shib4.cpp
index 90817d8e..6797c670 100644
--- a/apache/mod_shib4.cpp
+++ b/apache/mod_shib4.cpp
@@ -499,7 +499,7 @@ public:
     return DONE;
   }
   long sendRedirect(const char* url) {
-    HTTPResponse::sendRedirect(url);    
+    url = sanitizeURL(url);
     apr_table_set(m_req->headers_out, "Location", url);
 
     if (getRequestSettings().first->getBool(
diff --git a/fastcgi/shibauthorizer.cpp b/fastcgi/shibauthorizer.cpp
index 2bad8b68..3db6b4bc 100644
--- a/fastcgi/shibauthorizer.cpp
+++ b/fastcgi/shibauthorizer.cpp
@@ -229,7 +229,8 @@ public:
     }
 
     long sendRedirect(const char* url) {
-        HTTPResponse::sendRedirect(url);
+        url = sanitizeURL(url);
+        
         string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
           "Content-Type: text/html\r\n"
           "Content-Length: 40\r\n";
diff --git a/fastcgi/shibresponder.cpp b/fastcgi/shibresponder.cpp
index 81306421..0276e87f 100644
--- a/fastcgi/shibresponder.cpp
+++ b/fastcgi/shibresponder.cpp
@@ -190,7 +190,8 @@ public:
     }
 
     long sendRedirect(const char* url) {
-        HTTPResponse::sendRedirect(url);
+        url = sanitizeURL(url);
+        
         string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
           "Content-Type: text/html\r\n"
           "Content-Length: 40\r\n";
diff --git a/iis/IIS7Request.cpp b/iis/IIS7Request.cpp
index f753c089..a9c5c530 100644
--- a/iis/IIS7Request.cpp
+++ b/iis/IIS7Request.cpp
@@ -466,7 +466,7 @@ void IIS7Request::setResponseHeader(const char* name, const char* value, bool re
 
 long IIS7Request::sendRedirect(const char* url)
 {
-    HTTPResponse::sendRedirect(url);
+    url = sanitizeURL(url);
     
     if (getRequestSettings().first->getBool(
             RequestMapper::EXPIRE_REDIRECTS_PROP_NAME, RequestMapper::EXPIRE_REDIRECTS_PROP_DEFAULT)) {
diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp
index 4a564ab0..39d4235f 100644
--- a/shibsp/AbstractSPRequest.cpp
+++ b/shibsp/AbstractSPRequest.cpp
@@ -64,6 +64,13 @@ AbstractSPRequest::~AbstractSPRequest()
         m_mapper->unlock_shared();
 }
 
+vector<string> AbstractSPRequest::m_allowedSchemes;
+
+vector<string>& AbstractSPRequest::getAllowedSchemes()
+{
+    return m_allowedSchemes;
+}
+
 const Agent& AbstractSPRequest::getAgent() const
 {
     return m_agent;
@@ -531,6 +538,47 @@ bool AbstractSPRequest::isPriorityEnabled(Priority::Value level) const
     return m_log.isPriorityEnabled(level);
 }
 
+const char* AbstractSPRequest::sanitizeURL(const char* url)
+{
+    if (!url) {
+        throw domain_error("URL was null");
+    }
+
+    const char* ch;
+    for (ch=url; *ch; ++ch) {
+        if (iscntrl((unsigned char)(*ch))) {  // convert to unsigned to allow full range from 00-FF
+            throw domain_error("URL contained a control character.");
+        }
+    }
+
+    ch = strchr(url, ':');
+    if (!ch) {
+        throw domain_error("URL is missing a colon where expected; improper URL encoding?");
+    }
+    string s(url, ch - url);
+
+    for (const string& scheme : getAllowedSchemes()) {
+        if (strcasecmp(s.c_str(), scheme.c_str()) == 0) {
+            // Checks out, but absolutize if necessary.
+            if (*url == '/') {
+                // Compute a URL to the root of the site.
+                const char* scheme = getScheme();
+                m_absoluteHolder = string(scheme) + "://" + getHostname();
+                if (!isDefaultPort()) {
+                    m_absoluteHolder += ":" + boost::lexical_cast<string>(getPort());
+                }
+                m_absoluteHolder += url;
+                return m_absoluteHolder.c_str();
+            }
+            else {
+                return url;
+            }
+        }
+    }
+
+    throw domain_error("URL contains invalid scheme.");
+}
+
 void SPRequest::debug(const string& msg) const
 {
     log(Priority::SHIB_DEBUG, msg);
diff --git a/shibsp/AbstractSPRequest.h b/shibsp/AbstractSPRequest.h
index cd67b2af..85bf5d97 100644
--- a/shibsp/AbstractSPRequest.h
+++ b/shibsp/AbstractSPRequest.h
@@ -59,6 +59,16 @@ namespace shibsp {
     public:
         virtual ~AbstractSPRequest();
 
+        /**
+         * Returns a modifiable array of schemes to permit in sanitized URLs.
+         *
+         * <p>Updates to this array must be externally synchronized with any use
+         * of this class or its subclasses.
+         *
+         * @return  a mutable array of strings containing the schemes to permit
+         */
+        static std::vector<std::string>& getAllowedSchemes();
+
         // Virtual function overrides.
         const Agent& getAgent() const;
         RequestMapper::Settings getRequestSettings() const;
@@ -84,6 +94,16 @@ namespace shibsp {
         bool isPriorityEnabled(Priority::Value level) const;
 
     protected:
+        /**
+         * Check for unsafe URLs vulnerable to injection attacks and promote
+         * relative URLs to absolute based on current request.
+         *
+         * @param url   location to check/promote
+         * 
+         * @return sanitized and possibly altered URL
+         */
+        const char* sanitizeURL(const char* url);
+
         /**
          * Gets the transformed header name constructed from a raw input name by transforming
          * punctuation into underscores and prefixing with "HTTP_".
@@ -99,15 +119,19 @@ namespace shibsp {
         virtual const char* getLogContext() const;
 
     private:
+        static std::vector<std::string> m_allowedSchemes;
+
         Category& m_log;
         Agent& m_agent;
         mutable RequestMapper* m_mapper;
         mutable RequestMapper::Settings m_settings;
         std::string m_uri;
-        mutable std::string m_url;
+        mutable std::string m_url;        
         mutable std::string m_handlerURL;
         mutable std::unique_ptr<CGIParser> m_parser;
         mutable std::map<std::string,std::string> m_cookieMap;
+        // Holds URL when promoted to absolute.
+        std::string m_absoluteHolder;
     };
 
 #if defined (_MSC_VER)
diff --git a/shibsp/Agent.cpp b/shibsp/Agent.cpp
index 91ce3f51..6b888167 100644
--- a/shibsp/Agent.cpp
+++ b/shibsp/Agent.cpp
@@ -95,9 +95,14 @@ long Agent::handleError(SPRequest& request, exception* ex, bool mayRedirect) con
 
     if (mayRedirect && redirectErrors) {
         string loc(redirectErrors);
-        request.absolutize(loc);
         if (richEx) {
-            loc = loc + '?' + richEx->toQueryString();
+            if (loc.find('?') != string::npos) {
+                loc += '&';
+            }
+            else {
+                loc += '?';
+            }
+            loc += richEx->toQueryString();
         }
         return request.sendRedirect(loc.c_str());
     }
@@ -220,17 +225,20 @@ pair<bool,long> Agent::doAuthentication(SPRequest& request, bool handler) const
                 if (!qstr || !strstr(qstr, "shiblogoutdone=1")) {
                     // First leg of circuit, so we redirect to the logout endpoint specified with this URL as a return location.
                     string selfurl = request.getRequestURL();
-                    if (qstr)
+                    if (qstr) {
                         selfurl += '&';
-                    else
+                    }
+                    else {
                         selfurl += '?';
+                    }
                     selfurl += "shiblogoutdone=1";
                     string loc(requireLogoutWith);
-                    request.absolutize(loc);
-                    if (loc.find('?') != string::npos)
+                    if (loc.find('?') != string::npos) {
                         loc += '&';
-                    else
+                    }
+                    else {
                         loc += '?';
+                    }
                     loc += "return=" + AgentConfig::getConfig().getURLEncoder().encode(selfurl.c_str());
                     return make_pair(true, request.sendRedirect(loc.c_str()));
                 }
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index bf667822..f59dd5a5 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -49,8 +49,6 @@ handinclude_HEADERS = \
 
 ioinclude_HEADERS = \
 	io/CookieManager.h \
-	io/GenericRequest.h \
-	io/GenericResponse.h \
 	io/HTTPRequest.h \
 	io/HTTPResponse.h
 
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 1d47e233..61b82979 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -174,12 +174,10 @@ pair<bool,long> AbstractHandler::unwrapResponse(SPRequest& request, DDF& wrapped
 
     h = http["redirect"];
     if (h.isstring()) {
-        string dest(h.string());
-        request.absolutize(dest);
         if (limitRedirect) {
-            request.limitRedirect(dest.c_str());
+            request.limitRedirect(h.string());
         }
-        return make_pair(true, request.sendRedirect(dest.c_str()));
+        return make_pair(true, request.sendRedirect(h.string()));
     }
 
     h = http["response"];
diff --git a/shibsp/handler/impl/AttributeCheckerHandler.cpp b/shibsp/handler/impl/AttributeCheckerHandler.cpp
index 8aab8dfc..a8a9acc8 100644
--- a/shibsp/handler/impl/AttributeCheckerHandler.cpp
+++ b/shibsp/handler/impl/AttributeCheckerHandler.cpp
@@ -154,9 +154,7 @@ pair<bool,long> AttributeCheckerHandler::run(SPRequest& request, bool isHandler)
     }
 
     if (checked) {
-        string loc(returnURL);
-        request.absolutize(loc);
-        return make_pair(true, request.sendRedirect(loc.c_str()));
+        return make_pair(true, request.sendRedirect(returnURL));
     }
 
     if (m_flushSession && session) {
diff --git a/shibsp/handler/impl/LogoutConsumer.cpp b/shibsp/handler/impl/LogoutConsumer.cpp
index a0d4b7be..86756b01 100644
--- a/shibsp/handler/impl/LogoutConsumer.cpp
+++ b/shibsp/handler/impl/LogoutConsumer.cpp
@@ -236,15 +236,8 @@ pair <bool,long> LogoutConsumer::completeLogout(SPRequest& request, bool removeS
         dest = getHomeURL(request);
     }
 
-    // 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));
-    }
+    request.limitRedirect(dest);
+    return make_pair(true, request.sendRedirect(dest));
 }
 
 const char* LogoutConsumer::getHomeURL(SPRequest& request) const
diff --git a/shibsp/handler/impl/LogoutInitiator.cpp b/shibsp/handler/impl/LogoutInitiator.cpp
index f9e37275..a5824f3b 100644
--- a/shibsp/handler/impl/LogoutInitiator.cpp
+++ b/shibsp/handler/impl/LogoutInitiator.cpp
@@ -132,13 +132,6 @@ pair<bool,long> LogoutInitiator::run(SPRequest& request, bool isHandler) const
         }
     }
 
-    // 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));
-    }
+    request.limitRedirect(dest);
+    return make_pair(true, request.sendRedirect(dest));
 }
diff --git a/shibsp/handler/impl/TokenConsumer.cpp b/shibsp/handler/impl/TokenConsumer.cpp
index 809c63cb..2418e599 100644
--- a/shibsp/handler/impl/TokenConsumer.cpp
+++ b/shibsp/handler/impl/TokenConsumer.cpp
@@ -174,7 +174,6 @@ pair<bool,long> TokenConsumer::run(SPRequest& request, bool isHandler) const
 
         if (sessionHook) {
             string hook(sessionHook);
-            request.absolutize(hook);
 
             // Compute the return URL. We use a self-referential link plus a hook indicator to break the cycle.
             // The target also must be included.
diff --git a/shibsp/impl/DefaultAgent.cpp b/shibsp/impl/DefaultAgent.cpp
index 53f7a52c..98bc3f50 100644
--- a/shibsp/impl/DefaultAgent.cpp
+++ b/shibsp/impl/DefaultAgent.cpp
@@ -22,6 +22,7 @@
 
 #include "exceptions.h"
 #include "version.h"
+#include "AbstractSPRequest.h"
 #include "Agent.h"
 #include "AgentConfig.h"
 #include "RequestMapper.h"
@@ -151,8 +152,8 @@ void DefaultAgent::init()
     }
 
     const char* prop = getString(ALLOWED_SCHEMES_PROP_NAME, ALLOWED_SCHEMES_PROP_DEFAULT);
-    HTTPResponse::getAllowedSchemes().clear();
-    split_to_container(HTTPResponse::getAllowedSchemes(), prop);
+    AbstractSPRequest::getAllowedSchemes().clear();
+    split_to_container(AbstractSPRequest::getAllowedSchemes(), prop);
 
     prop = getString(EXTRA_AUTH_TYPES_PROP_NAME);
     if (prop) {
diff --git a/shibsp/io/GenericRequest.h b/shibsp/io/GenericRequest.h
deleted file mode 100644
index b1a58b96..00000000
--- a/shibsp/io/GenericRequest.h
+++ /dev/null
@@ -1,168 +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.
- */
-
-/**
- * @file shibsp/io/GenericRequest.h
- *
- * Interface to generic protocol requests handled by agents.
- */
-
-#ifndef __shibsp_genreq_h__
-#define __shibsp_genreq_h__
-
-#include <shibsp/base.h>
-
-#include <string>
-#include <vector>
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4251 )
-#endif
-
-    /**
-     * Interface to generic protocol requests handled by agents.
-     *
-     * <p>This interface need not be threadsafe.</p>
-     */
-    class SHIBSP_API GenericRequest {
-        MAKE_NONCOPYABLE(GenericRequest);
-    protected:
-        GenericRequest();
-    public:
-        virtual ~GenericRequest();
-
-        /**
-         * Returns the URL scheme of the request (http, https, ftp, ldap, etc.)
-         *
-         * @return the URL scheme
-         */
-        virtual const char* getScheme() const=0;
-
-        /**
-         * Returns true iff the request is over a confidential channel.
-         *
-         * @return confidential channel indicator
-         */
-        virtual bool isSecure() const=0;
-
-        /**
-         * Returns hostname of service that received request.
-         *
-         * @return hostname of service
-         */
-        virtual const char* getHostname() const=0;
-
-        /**
-         * Returns incoming port.
-         *
-         * @return  incoming port
-         */
-        virtual int getPort() const=0;
-
-        /**
-         * Returns true iff the request port is the default port for the request protocol.
-         *
-         * @return  default port indicator
-         */
-        virtual bool isDefaultPort() const;
-
-        /**
-         * Returns the MIME type of the request, if known.
-         *
-         * @return the MIME type, or an empty string
-         */
-        virtual std::string getContentType() const=0;
-
-        /**
-         * Returns the length of the request body, if known.
-         *
-         * @return the content length, or -1 if unknown
-         */
-        virtual long getContentLength() const=0;
-
-        /**
-         * Returns the raw request body.
-         *
-         * @return the request body, or nullptr
-         */
-        virtual const char* getRequestBody() const=0;
-
-        /**
-         * Returns a decoded named parameter value from the request.
-         * If a parameter has multiple values, only one will be returned.
-         *
-         * @param name  the name of the parameter to return
-         * @return a single parameter value or nullptr
-         */
-        virtual const char* getParameter(const char* name) const=0;
-
-        /**
-         * Returns all of the decoded values of a named parameter from the request.
-         * All values found will be returned.
-         *
-         * @param name      the name of the parameter to return
-         * @param values    a vector in which to return pointers to the decoded values
-         * @return  the number of values returned
-         */
-        virtual std::vector<const char*>::size_type getParameters(
-            const char* name, std::vector<const char*>& values
-            ) const=0;
-
-        /**
-         * Returns the transport-authenticated identity associated with the request,
-         * if authentication is solely handled by the transport.
-         *
-         * @return the authenticated username or an empty string
-         */
-        virtual std::string getRemoteUser() const=0;
-
-        /**
-         * Gets the authentication type associated with the request.
-         *
-         * @return  the authentication type or nullptr
-         */
-        virtual std::string getAuthType() const=0;
-
-        /**
-         * Returns the IP address of the client.
-         *
-         * @return the client's IP address
-         */
-        virtual std::string getRemoteAddr() const=0;
-
-        /**
-         * Returns the IP address of the server.
-         *
-         * @return the server's IP address
-         */
-        virtual std::string getLocalAddr() const=0;
-
-        /**
-         * Converts a relative URL into an absolute one based on the properties of the request.
-         *
-         * @param url   input URL to convert, will be modified in place
-         */
-        virtual void absolutize(std::string& url) const;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-};
-
-#endif /* __shibsp_genreq_h__ */
diff --git a/shibsp/io/GenericResponse.h b/shibsp/io/GenericResponse.h
deleted file mode 100644
index 94cadf2b..00000000
--- a/shibsp/io/GenericResponse.h
+++ /dev/null
@@ -1,78 +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.
- */
-
-/**
- * @file shibsp/io/GenericResponse.h
- * 
- * Interface to generic protocol responses issued by agents.
- */
-
-#ifndef __shibsp_genres_h__
-#define __shibsp_genres_h__
-
-#include <shibsp/base.h>
-
-#include <iostream>
-
-namespace shibsp {
-    
-    /**
-     * Interface to generic protocol responses issued by agents.
-     * 
-     * <p>This interface need not be threadsafe.</p>
-     */
-    class SHIBSP_API GenericResponse {
-        MAKE_NONCOPYABLE(GenericResponse);
-    protected:
-        GenericResponse();
-    public:
-        virtual ~GenericResponse();
-
-        /**
-         * Sets or clears the MIME type of the response.
-         * 
-         * @param type the MIME type, or nullptr to clear
-         */
-        virtual void setContentType(const char* type=nullptr)=0;
-
-        /**
-         * Sends a completed response to the client along with a
-         * transport-specific "OK" indication. Used for "normal" responses.
-         * 
-         * @param inputStream   reference to source of response data
-         * @return a result code to return from the calling MessageEncoder
-         */
-        virtual long sendResponse(std::istream& inputStream)=0;
-
-        /**
-         * Sends an "error" response to the client along with a
-         * transport-specific error indication.
-         * 
-         * @param inputStream   reference to source of response data
-         * @return a result code to return from the calling MessageEncoder
-         */
-        virtual long sendError(std::istream& inputStream)=0;
-
-        /**
-         * Sends a completed response to the client.
-         * 
-         * @param inputStream   reference to source of response data
-         * @param status        transport-specific status to return
-         * @return a result code to return from the calling MessageEncoder
-         */
-        virtual long sendResponse(std::istream& inputStream, long status)=0;
-    };
-};
-
-#endif /* __shibsp_genres_h__ */
diff --git a/shibsp/io/HTTPRequest.h b/shibsp/io/HTTPRequest.h
index 3492a742..643cb7d0 100644
--- a/shibsp/io/HTTPRequest.h
+++ b/shibsp/io/HTTPRequest.h
@@ -21,7 +21,7 @@
 #ifndef __shibsp_httpreq_h__
 #define __shibsp_httpreq_h__
 
-#include <shibsp/io/GenericRequest.h>
+#include <shibsp/base.h>
 
 #include <map>
 
@@ -37,19 +37,124 @@ namespace shibsp {
      * 
      * <p>To supply information from the surrounding web server environment,
      * a shim must be supplied in the form of this interface to adapt the
-     * library to different proprietary server APIs.</p>
+     * library to different proprietary server APIs. Typically this
+     * is done via implementation of SPRequest.</p>
      * 
      * <p>This interface need not be threadsafe.</p>
      */
-    class SHIBSP_API HTTPRequest : public GenericRequest {
+    class SHIBSP_API HTTPRequest {
+        MAKE_NONCOPYABLE(HTTPRequest);
     protected:
         HTTPRequest();
     public:
         virtual ~HTTPRequest();
 
-        bool isSecure() const;
-        bool isDefaultPort() const;
-          
+            /**
+         * Returns the URL scheme of the request (http, https, ftp, ldap, etc.)
+         *
+         * @return the URL scheme
+         */
+        virtual const char* getScheme() const=0;
+
+        /**
+         * Returns true iff the request is over a confidential channel.
+         *
+         * @return confidential channel indicator
+         */
+        virtual bool isSecure() const;
+
+        /**
+         * Returns hostname of service that received request.
+         *
+         * @return hostname of service
+         */
+        virtual const char* getHostname() const=0;
+
+        /**
+         * Returns incoming port.
+         *
+         * @return  incoming port
+         */
+        virtual int getPort() const=0;
+
+        /**
+         * Returns true iff the request port is the default port for the request protocol.
+         *
+         * @return  default port indicator
+         */
+        virtual bool isDefaultPort() const;
+
+        /**
+         * Returns the MIME type of the request, if known.
+         *
+         * @return the MIME type, or an empty string
+         */
+        virtual std::string getContentType() const=0;
+
+        /**
+         * Returns the length of the request body, if known.
+         *
+         * @return the content length, or -1 if unknown
+         */
+        virtual long getContentLength() const=0;
+
+        /**
+         * Returns the raw request body.
+         *
+         * @return the request body, or nullptr
+         */
+        virtual const char* getRequestBody() const=0;
+
+        /**
+         * Returns a decoded named parameter value from the request.
+         * If a parameter has multiple values, only one will be returned.
+         *
+         * @param name  the name of the parameter to return
+         * @return a single parameter value or nullptr
+         */
+        virtual const char* getParameter(const char* name) const=0;
+
+        /**
+         * Returns all of the decoded values of a named parameter from the request.
+         * All values found will be returned.
+         *
+         * @param name      the name of the parameter to return
+         * @param values    a vector in which to return pointers to the decoded values
+         * @return  the number of values returned
+         */
+        virtual std::vector<const char*>::size_type getParameters(
+            const char* name, std::vector<const char*>& values
+            ) const=0;
+
+        /**
+         * Returns the transport-authenticated identity associated with the request,
+         * if authentication is solely handled by the transport.
+         *
+         * @return the authenticated username or an empty string
+         */
+        virtual std::string getRemoteUser() const=0;
+
+        /**
+         * Gets the authentication type associated with the request.
+         *
+         * @return  the authentication type or nullptr
+         */
+        virtual std::string getAuthType() const=0;
+
+        /**
+         * Returns the IP address of the client.
+         *
+         * @return the client's IP address
+         */
+        virtual std::string getRemoteAddr() const=0;
+
+        /**
+         * Returns the IP address of the server.
+         *
+         * @return the server's IP address
+         */
+        virtual std::string getLocalAddr() const=0;
+
         /**
          * Returns the HTTP method of the request (GET, POST, etc.)
          * 
diff --git a/shibsp/io/HTTPResponse.h b/shibsp/io/HTTPResponse.h
index e215f860..af664dc3 100644
--- a/shibsp/io/HTTPResponse.h
+++ b/shibsp/io/HTTPResponse.h
@@ -21,7 +21,7 @@
 #ifndef __shibsp_httpres_h__
 #define __shibsp_httpres_h__
 
-#include <shibsp/io/GenericResponse.h>
+#include <shibsp/base.h>
 
 #include <string>
 #include <vector>
@@ -38,38 +38,63 @@ namespace shibsp {
      * 
      * <p>To supply information to the surrounding web server environment,
      * a shim must be supplied in the form of this interface to adapt the
-     * library to different proprietary server APIs.</p>
+     * library to different proprietary server APIs. Typically this
+     * is done via implementation of SPRequest.</p>
      * 
      * <p>This interface need not be threadsafe.</p>
      */
-    class SHIBSP_API HTTPResponse : public GenericResponse {
+    class SHIBSP_API HTTPResponse {
+        MAKE_NONCOPYABLE(HTTPResponse);
     protected:
         HTTPResponse();
     public:
         virtual ~HTTPResponse();
         
-        void setContentType(const char* type);
-        
         /**
          * Sets, adds, or clears a response header.
          * 
+         * <p>The default implementation polices name and value for control characters.</p>
+         * 
          * @param name  header name
          * @param value value to set, or nullptr to clear
          * @param replace true iff this should replace existing header(s)
          */
         virtual void setResponseHeader(const char* name, const char* value, bool replace = false);
 
+        /**
+         * Sets or clears the MIME type of the response.
+         * 
+         * @param type the MIME type, or nullptr to clear
+         */
+        virtual void setContentType(const char* type=nullptr);
+
+        /**
+         * Sends a completed response to the client.
+         * 
+         * @param inputStream   reference to source of response data
+         * @param status        transport-specific status to return
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendResponse(std::istream& inputStream, long status=SHIBSP_HTTP_STATUS_OK)=0;
+
+        /**
+         * Sends an "error" response to the client along with a
+         * transport-specific error indication.
+         * 
+         * @param inputStream   reference to source of response data
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendError(std::istream& inputStream);
+        
         /**
          * Redirect the client to the specified URL and complete the response.
          * 
          * <p>Any headers previously set will be sent ahead of the redirect.
          *
-         * <p>The URL will be validated with the sanitizeURL method below.
-         *
          * @param url   location to redirect client
          * @return a result code to return
          */
-        virtual long sendRedirect(const char* url);
+        virtual long sendRedirect(const char* url)=0;
         
         /** Some common HTTP status codes. */
         enum status_t {
@@ -82,31 +107,6 @@ namespace shibsp {
             SHIBSP_HTTP_STATUS_NOTFOUND = 404,
             SHIBSP_HTTP_STATUS_ERROR = 500
         };
-        
-        long sendError(std::istream& inputStream);
-
-        using GenericResponse::sendResponse;
-        long sendResponse(std::istream& inputStream);
-
-        /**
-         * Returns a modifiable array of schemes to permit in sanitized URLs.
-         *
-         * <p>Updates to this array must be externally synchronized with any use
-         * of this class or its subclasses.
-         *
-         * @return  a mutable array of strings containing the schemes to permit
-         */
-        static std::vector<std::string>& getAllowedSchemes();
-
-        /**
-         * Manually check for unsafe URLs vulnerable to injection attacks.
-         *
-         * @param url   location to check
-         */
-        static void sanitizeURL(const char* url);
-
-    private:
-        static std::vector<std::string> m_allowedSchemes;
     };
 
 #if defined (_MSC_VER)
diff --git a/shibsp/io/impl/HTTPRequest.cpp b/shibsp/io/impl/HTTPRequest.cpp
index 10a09a6f..cdf78739 100644
--- a/shibsp/io/impl/HTTPRequest.cpp
+++ b/shibsp/io/impl/HTTPRequest.cpp
@@ -29,33 +29,6 @@
 using namespace shibsp;
 using namespace std;
 
-GenericRequest::GenericRequest()
-{
-}
-
-GenericRequest::~GenericRequest()
-{
-}
-
-bool GenericRequest::isDefaultPort() const
-{
-    return false;
-}
-
-void GenericRequest::absolutize(string& url) const
-{
-    if (url.empty())
-        url = '/';
-    if (url[0] == '/') {
-        // Compute a URL to the root of the site.
-        const char* scheme = getScheme();
-        string root = string(scheme) + "://" + getHostname();
-        if (!isDefaultPort())
-            root += ":" + boost::lexical_cast<string>(getPort());
-        url = root + url;
-    }
-}
-
 HTTPRequest::HTTPRequest()
 {
 }
diff --git a/shibsp/io/impl/HTTPResponse.cpp b/shibsp/io/impl/HTTPResponse.cpp
index 1db1c566..f2986e9e 100644
--- a/shibsp/io/impl/HTTPResponse.cpp
+++ b/shibsp/io/impl/HTTPResponse.cpp
@@ -32,43 +32,6 @@
 using namespace shibsp;
 using namespace std;
 
-GenericResponse::GenericResponse()
-{
-}
-
-GenericResponse::~GenericResponse()
-{
-}
-
-vector<string> HTTPResponse::m_allowedSchemes;
-
-vector<string>& HTTPResponse::getAllowedSchemes()
-{
-    return m_allowedSchemes;
-}
-
-void HTTPResponse::sanitizeURL(const char* url)
-{
-    const char* ch;
-    for (ch=url; *ch; ++ch) {
-        if (iscntrl((unsigned char)(*ch)))  // convert to unsigned to allow full range from 00-FF
-            throw domain_error("URL contained a control character.");
-    }
-
-    ch = strchr(url, ':');
-    if (!ch)
-        throw domain_error("URL is missing a colon where expected; improper URL encoding?");
-    string s(url, ch - url);
-
-    for (const string& scheme : m_allowedSchemes) {
-        if (strcasecmp(s.c_str(), scheme.c_str()) == 0) {
-            return;
-        }
-    }
-
-    throw domain_error("URL contains invalid scheme.");
-}
-
 HTTPResponse::HTTPResponse()
 {
 }
@@ -99,18 +62,7 @@ void HTTPResponse::setResponseHeader(const char* name, const char* value, bool)
     }
 }
 
-long HTTPResponse::sendRedirect(const char* url)
-{
-    sanitizeURL(url);
-    return SHIBSP_HTTP_STATUS_MOVED;
-}
-
 long HTTPResponse::sendError(istream& inputStream)
 {
     return sendResponse(inputStream, SHIBSP_HTTP_STATUS_ERROR);
 }
-
-long HTTPResponse::sendResponse(istream& inputStream)
-{
-    return sendResponse(inputStream, SHIBSP_HTTP_STATUS_OK);
-}
diff --git a/tests/DummyRequest.h b/tests/DummyRequest.h
index bc0773c7..c0b1dad8 100644
--- a/tests/DummyRequest.h
+++ b/tests/DummyRequest.h
@@ -46,6 +46,7 @@ namespace shibsp {
         std::string getRemoteAddr() const { return m_addr; }
         std::string getLocalAddr() const { return ""; }
         std::string getAuthType() const { return ""; }
+        long sendRedirect(const char* url) { return SHIBSP_HTTP_STATUS_MOVED; }
         long sendResponse(std::istream&, long status) { return status; }
         void clearHeader(const char* name) {}
         void setHeader(const char* name, const char* value) {}

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


More information about the commits mailing list