https://issues.shibboleth.net/jira/browse/SSPCPP-161
authorScott Cantor <cantor.2@osu.edu>
Sat, 18 Oct 2008 02:12:21 +0000 (02:12 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sat, 18 Oct 2008 02:12:21 +0000 (02:12 +0000)
shibsp/Application.cpp
shibsp/Application.h
shibsp/ServiceProvider.cpp
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/impl/XMLServiceProvider.cpp

index 8e41cab..6ee7919 100644 (file)
@@ -68,6 +68,21 @@ pair<string,const char*> Application::getCookieNameProps(const char* prefix, tim
     return pair<string,const char*>(prefix,defProps);
 }
 
+void Application::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
+{
+    request.clearHeader(rawname, cginame);
+}
+
+void Application::setHeader(SPRequest& request, const char* name, const char* value) const
+{
+    request.setHeader(name, value);
+}
+
+string Application::getSecureHeader(const SPRequest& request, const char* name) const
+{
+    return request.getSecureHeader(name);
+}
+
 void Application::clearAttributeHeaders(SPRequest& request) const
 {
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
index c7352a2..f1d99f2 100644 (file)
@@ -206,6 +206,33 @@ namespace shibsp {
         virtual const std::vector<std::string>& getRemoteUserAttributeIds() const=0;
 
         /**
+         * Ensures no value exists for a request header, allowing for application-specific customization.
+         * 
+         * @param request  SP request to modify
+         * @param rawname  raw name of header to clear
+         * @param cginame  CGI-equivalent name of header, <strong>MUST</strong> begin with "HTTP_".
+         */
+        virtual void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;
+
+        /**
+         * Sets a value for a request header allowing for application-specific customization.
+         * 
+         * @param request   SP request to modify
+         * @param name      name of header to set
+         * @param value     value to set
+         */
+        virtual void setHeader(SPRequest& request, const char* name, const char* value) const;
+
+        /**
+         * Returns a non-spoofable request header value allowing for application-specific customization.
+         * 
+         * @param request   SP request to access
+         * @param name      the name of the secure header to return
+         * @return  the header's value, or an empty string
+         */
+        virtual std::string getSecureHeader(const SPRequest& request, const char* name) const;
+
+        /**
          * Clears any headers that may be used to hold attributes after export.
          *
          * @param request   SP request to clear
index 958799f..b64d8ee 100644 (file)
@@ -116,16 +116,16 @@ namespace shibsp {
     }
 
     void SHIBSP_DLLLOCAL clearHeaders(SPRequest& request) {
-        request.clearHeader("Shib-Session-ID", "HTTP_SHIB_SESSION_ID");
-        request.clearHeader("Shib-Identity-Provider", "HTTP_SHIB_IDENTITY_PROVIDER");
-        request.clearHeader("Shib-Authentication-Method", "HTTP_SHIB_AUTHENTICATION_METHOD");
-        request.clearHeader("Shib-Authentication-Instant", "HTTP_SHIB_AUTHENTICATION_INSTANT");
-        request.clearHeader("Shib-AuthnContext-Class", "HTTP_SHIB_AUTHNCONTEXT_CLASS");
-        request.clearHeader("Shib-AuthnContext-Decl", "HTTP_SHIB_AUTHNCONTEXT_DECL");
-        request.clearHeader("Shib-Assertion-Count", "HTTP_SHIB_ASSERTION_COUNT");
+        const Application& app = request.getApplication();
+        app.clearHeader(request, "Shib-Session-ID", "HTTP_SHIB_SESSION_ID");
+        app.clearHeader(request, "Shib-Identity-Provider", "HTTP_SHIB_IDENTITY_PROVIDER");
+        app.clearHeader(request, "Shib-Authentication-Method", "HTTP_SHIB_AUTHENTICATION_METHOD");
+        app.clearHeader(request, "Shib-Authentication-Instant", "HTTP_SHIB_AUTHENTICATION_INSTANT");
+        app.clearHeader(request, "Shib-AuthnContext-Class", "HTTP_SHIB_AUTHNCONTEXT_CLASS");
+        app.clearHeader(request, "Shib-AuthnContext-Decl", "HTTP_SHIB_AUTHNCONTEXT_DECL");
+        app.clearHeader(request, "Shib-Assertion-Count", "HTTP_SHIB_ASSERTION_COUNT");
+        app.clearAttributeHeaders(request);
         request.clearHeader("REMOTE_USER", "HTTP_REMOTE_USER");
-        //request.clearHeader("Shib-Application-ID");   handle inside app method
-        request.getApplication().clearAttributeHeaders(request);
     }
 };
 
@@ -355,24 +355,24 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                        return make_pair(false,0L);     // just bail silently
         }
 
-        request.setHeader("Shib-Application-ID", app->getId());
-        request.setHeader("Shib-Session-ID", session->getID());
+        app->setHeader(request, "Shib-Application-ID", app->getId());
+        app->setHeader(request, "Shib-Session-ID", session->getID());
 
         // Export the IdP name and Authn method/context info.
         const char* hval = session->getEntityID();
         if (hval)
-            request.setHeader("Shib-Identity-Provider", hval);
+            app->setHeader(request, "Shib-Identity-Provider", hval);
         hval = session->getAuthnInstant();
         if (hval)
-            request.setHeader("Shib-Authentication-Instant", hval);
+            app->setHeader(request, "Shib-Authentication-Instant", hval);
         hval = session->getAuthnContextClassRef();
         if (hval) {
-            request.setHeader("Shib-Authentication-Method", hval);
-            request.setHeader("Shib-AuthnContext-Class", hval);
+            app->setHeader(request, "Shib-Authentication-Method", hval);
+            app->setHeader(request, "Shib-AuthnContext-Class", hval);
         }
         hval = session->getAuthnContextDeclRef();
         if (hval)
-            request.setHeader("Shib-AuthnContext-Decl", hval);
+            app->setHeader(request, "Shib-AuthnContext-Decl", hval);
 
         // Maybe export the assertion keys.
         pair<bool,bool> exp=settings.first->getBool("exportAssertion");
@@ -397,16 +397,16 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                     *(exportName.rbegin()) = '0' + (count%10);
                     *(++exportName.rbegin()) = '0' + (count/10);
                     string fullURL = baseURL + encoder->encode(*tokenids);
-                    request.setHeader(exportName.c_str(), fullURL.c_str());
+                    app->setHeader(request, exportName.c_str(), fullURL.c_str());
                 }
-                request.setHeader("Shib-Assertion-Count", exportName.c_str() + 15);
+                app->setHeader(request, "Shib-Assertion-Count", exportName.c_str() + 15);
             }
         }
 
         // Export the attributes.
         const multimap<string,const Attribute*>& attributes = session->getIndexedAttributes();
         for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) {
-            string header(request.getSecureHeader(a->first.c_str()));
+            string header(app->getSecureHeader(request, a->first.c_str()));
             const vector<string>& vals = a->second->getSerializedValues();
             for (vector<string>::const_iterator v = vals.begin(); v!=vals.end(); ++v) {
                 if (!header.empty())
@@ -424,7 +424,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                     header += (*v);
                 }
             }
-            request.setHeader(a->first.c_str(), header.c_str());
+            app->setHeader(request, a->first.c_str(), header.c_str());
         }
 
         // Check for REMOTE_USER.
index 197b046..83b2f85 100644 (file)
@@ -351,17 +351,6 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
             // Copy over any pushed attributes.
             if (!resolvedAttributes.empty())
                 ctx->getResolvedAttributes().insert(ctx->getResolvedAttributes().end(), resolvedAttributes.begin(), resolvedAttributes.end());
-
-            // Attach global prefix if needed.
-            pair<bool,const char*> prefix = application.getString("attributePrefix");
-            if (prefix.first) {
-                for (vector<Attribute*>::iterator a = ctx->getResolvedAttributes().begin(); a != ctx->getResolvedAttributes().end(); ++a) {
-                    vector<string>& ids = (*a)->getAliases();
-                    for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
-                        *id = prefix.second + *id;
-                }
-            }
-
             return ctx.release();
         }
     }
@@ -369,19 +358,8 @@ ResolutionContext* AssertionConsumerService::resolveAttributes(
         m_log.error("attribute resolution failed: %s", ex.what());
     }
 
-    if (!resolvedAttributes.empty()) {
-        // Attach global prefix if needed.
-        pair<bool,const char*> prefix = application.getString("attributePrefix");
-        if (prefix.first) {
-            for (vector<Attribute*>::iterator a = resolvedAttributes.begin(); a != resolvedAttributes.end(); ++a) {
-                vector<string>& ids = (*a)->getAliases();
-                for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
-                    *id = prefix.second + *id;
-            }
-        }
-
+    if (!resolvedAttributes.empty())
         return new DummyContext(resolvedAttributes);
-    }
     return NULL;
 }
 
index d6e0e09..67fba2d 100644 (file)
@@ -28,6 +28,7 @@
 #include "ServiceProvider.h"
 #include "SessionCache.h"
 #include "SPConfig.h"
+#include "SPRequest.h"
 #include "handler/SessionInitiator.h"
 #include "remoting/ListenerService.h"
 #include "util/DOMPropertySet.h"
@@ -139,6 +140,10 @@ namespace {
             return (m_remoteUsers.empty() && m_base) ? m_base->getRemoteUserAttributeIds() : m_remoteUsers;
         }
 
+        void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;
+        void setHeader(SPRequest& request, const char* name, const char* value) const;
+        string getSecureHeader(const SPRequest& request, const char* name) const;
+
         const SessionInitiator* getDefaultSessionInitiator() const;
         const SessionInitiator* getSessionInitiatorById(const char* id) const;
         const Handler* getDefaultAssertionConsumerService() const;
@@ -166,6 +171,7 @@ namespace {
         void cleanup();
         const XMLApplication* m_base;
         string m_hash;
+        std::pair<std::string,std::string> m_attributePrefix;
 #ifndef SHIBSP_LITE
         MetadataProvider* m_metadata;
         TrustEngine* m_trust;
@@ -483,6 +489,18 @@ XMLApplication::XMLApplication(
             m_hash += (DIGITS[0x0F & *ch]);
         }
 
+        // Populate prefix pair.
+        m_attributePrefix.second = "HTTP_";
+        pair<bool,const char*> prefix = getString("attributePrefix");
+        if (prefix.first) {
+            m_attributePrefix.first = prefix.second;
+            const char* pch = prefix.second;
+            while (*pch) {
+                m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');
+                pch++;
+            }
+        }
+
         // Load attribute ID lists for REMOTE_USER and header clearing.
         if (conf.isEnabled(SPConfig::InProcess)) {
             pair<bool,const char*> attributes = getString("REMOTE_USER");
@@ -506,9 +524,9 @@ XMLApplication::XMLApplication(
 
             attributes = getString("unsetHeaders");
             if (attributes.first) {
-                string transformedprefix("HTTP_");
+                string transformedprefix(m_attributePrefix.second);
                 const char* pch;
-                pair<bool,const char*> prefix = getString("metadataAttributePrefix");
+                prefix = getString("metadataAttributePrefix");
                 if (prefix.first) {
                     pch = prefix.second;
                     while (*pch) {
@@ -534,13 +552,14 @@ XMLApplication::XMLApplication(
                         transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                         pch++;
                     }
-                    m_unsetHeaders.push_back(pair<string,string>(start,string("HTTP_") + transformed));
+
+                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
                     if (prefix.first)
-                        m_unsetHeaders.push_back(pair<string,string>(string(prefix.second) + start, transformedprefix + transformed));
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
                     start = pos ? pos+1 : NULL;
                 }
                 free(dup);
-                m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
             }
         }
 
@@ -805,18 +824,20 @@ XMLApplication::XMLApplication(
                     Locker extlock(m_attrExtractor);
                     m_attrExtractor->getAttributeIds(unsetHeaders);
                 }
+                else if (m_base && m_base->m_attrExtractor) {
+                    Locker extlock(m_base->m_attrExtractor);
+                    m_base->m_attrExtractor->getAttributeIds(unsetHeaders);
+                }
                 if (m_attrResolver) {
                     Locker reslock(m_attrResolver);
                     m_attrResolver->getAttributeIds(unsetHeaders);
                 }
-                if (unsetHeaders.empty()) {
-                    if (m_base)
-                        m_unsetHeaders.insert(m_unsetHeaders.end(), m_base->m_unsetHeaders.begin(), m_base->m_unsetHeaders.end());
-                    else
-                        m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
+                else if (m_base && m_base->m_attrResolver) {
+                    Locker extlock(m_base->m_attrResolver);
+                    m_base->m_attrResolver->getAttributeIds(unsetHeaders);
                 }
-                else {
-                    string transformedprefix("HTTP_");
+                if (!unsetHeaders.empty()) {
+                    string transformedprefix(m_attributePrefix.second);
                     const char* pch;
                     pair<bool,const char*> prefix = getString("metadataAttributePrefix");
                     if (prefix.first) {
@@ -833,12 +854,12 @@ XMLApplication::XMLApplication(
                             transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                             pch++;
                         }
-                        m_unsetHeaders.push_back(pair<string,string>(*hdr, string("HTTP_") + transformed));
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
                         if (prefix.first)
-                            m_unsetHeaders.push_back(pair<string,string>(string(prefix.second) + *hdr, transformedprefix + transformed));
+                            m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
                     }
-                    m_unsetHeaders.push_back(pair<string,string>("Shib-Application-ID","HTTP_SHIB_APPLICATION_ID"));
                 }
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
             }
         }
 
@@ -1075,6 +1096,49 @@ string XMLApplication::getNotificationURL(const char* resource, bool front, unsi
     return notifyURL;
 }
 
+void XMLApplication::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
+{
+    if (!m_attributePrefix.first.empty()) {
+        string temp = m_attributePrefix.first + rawname;
+        string temp2 = m_attributePrefix.second + (cginame + 5);
+        request.clearHeader(temp.c_str(), temp2.c_str());
+    }
+    else if (m_base) {
+        m_base->clearHeader(request, rawname, cginame);
+    }
+    else {
+        request.clearHeader(rawname, cginame);
+    }
+}
+
+void XMLApplication::setHeader(SPRequest& request, const char* name, const char* value) const
+{
+    if (!m_attributePrefix.first.empty()) {
+        string temp = m_attributePrefix.first + name;
+        request.setHeader(temp.c_str(), value);
+    }
+    else if (m_base) {
+        m_base->setHeader(request, name, value);
+    }
+    else {
+        request.setHeader(name, value);
+    }
+}
+
+string XMLApplication::getSecureHeader(const SPRequest& request, const char* name) const
+{
+    if (!m_attributePrefix.first.empty()) {
+        string temp = m_attributePrefix.first + name;
+        return request.getSecureHeader(temp.c_str());
+    }
+    else if (m_base) {
+        return m_base->getSecureHeader(request,name);
+    }
+    else {
+        return request.getSecureHeader(name);
+    }
+}
+
 const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const
 {
     if (m_sessionInitDefault) return m_sessionInitDefault;