Add protocol family property to protocol handlers, and fix up error handling to recog...
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Tue, 10 Aug 2010 17:38:58 +0000 (17:38 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Tue, 10 Aug 2010 17:38:58 +0000 (17:38 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@3290 cb58f699-b61c-0410-a6fe-9272a202ed29

16 files changed:
adfs/adfs.cpp
shibsp/handler/AssertionConsumerService.h
shibsp/handler/Handler.h
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/handler/impl/SAML1Consumer.cpp
shibsp/handler/impl/SAML2ArtifactResolution.cpp
shibsp/handler/impl/SAML2Consumer.cpp
shibsp/handler/impl/SAML2Logout.cpp
shibsp/handler/impl/SAML2LogoutInitiator.cpp
shibsp/handler/impl/SAML2NameIDMgmt.cpp
shibsp/handler/impl/SAML2SessionInitiator.cpp
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/handler/impl/WAYFSessionInitiator.cpp
shibsp/shibsp-lite.vcxproj
shibsp/shibsp-lite.vcxproj.filters

index c957c19..333249f 100644 (file)
@@ -90,6 +90,10 @@ namespace {
         ADFSDecoder() : m_ns(WSTRUST_NS) {}
         virtual ~ADFSDecoder() {}
 
+        const XMLCh* getProtocolFamily() const {
+            return m_ns.get();
+        }
+
         XMLObject* decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const;
 
     protected:
@@ -140,6 +144,10 @@ namespace {
         pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
+        const XMLCh* getProtocolFamily() const {
+            return m_binding.get();
+        }
+
     private:
         pair<bool,long> doRequest(
             const Application& application,
@@ -156,13 +164,10 @@ namespace {
 
     class SHIBSP_DLLLOCAL ADFSConsumer : public shibsp::AssertionConsumerService
     {
+        auto_ptr_XMLCh m_protocol;
     public:
         ADFSConsumer(const DOMElement* e, const char* appId)
-            : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.ADFS"))
-#ifndef SHIBSP_LITE
-                ,m_protocol(WSFED_NS)
-#endif
-            {}
+            : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".SSO.ADFS")), m_protocol(WSFED_NS) {}
         virtual ~ADFSConsumer() {}
 
 #ifndef SHIBSP_LITE
@@ -171,8 +176,6 @@ namespace {
             role.addSupport(m_protocol.get());
         }
 
-        auto_ptr_XMLCh m_protocol;
-
     private:
         void implementProtocol(
             const Application& application,
@@ -182,6 +185,10 @@ namespace {
             const PropertySet*,
             const XMLObject& xmlObject
             ) const;
+#else
+        const XMLCh* getProtocolFamily() const {
+            return m_protocol.get();
+        }
 #endif
     };
 
@@ -219,6 +226,9 @@ namespace {
             return "LogoutInitiator";
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return m_binding.get();
+        }
 
     private:
         pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session) const;
@@ -254,7 +264,7 @@ namespace {
             auto_ptr_XMLCh widen(hurl.c_str());
             SingleLogoutService* ep = SingleLogoutServiceBuilder::buildSingleLogoutService();
             ep->setLocation(widen.get());
-            ep->setBinding(m_login.m_protocol.get());
+            ep->setBinding(m_login.getProtocolFamily());
             role.getSingleLogoutServices().push_back(ep);
         }
 
@@ -262,6 +272,9 @@ namespace {
             return m_login.getType();
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return m_login.getProtocolFamily();
+        }
 
     private:
         ADFSConsumer m_login;
@@ -378,12 +391,9 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
     }
 
     // Validate the ACS for use with this protocol.
-    pair<bool,const XMLCh*> ACSbinding = ACS->getXMLString("Binding");
-    if (ACSbinding.first) {
-        if (!XMLString::equals(ACSbinding.second, m_binding.get())) {
-            m_log.error("configured or requested ACS has non-ADFS binding");
-            throw ConfigurationException("Configured or requested ACS has non-ADFS binding ($1).", params(1, ACSbinding.second));
-        }
+    if (!XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
+        m_log.error("configured or requested ACS has non-ADFS binding");
+        throw ConfigurationException("Configured or requested ACS has non-ADFS binding ($1).", params(1, ACS->getString("Binding").second));
     }
 
     // Since we're not passing by index, we need to fully compute the return URL.
index a7618fb..1233268 100644 (file)
@@ -174,7 +174,7 @@ namespace shibsp {
 
     public:
         const char* getType() const;
-
+        const XMLCh* getProtocolFamily() const;
 #endif
     private:
         std::pair<bool,long> processMessage(
index 24bb798..624d983 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2009 Internet2
+ *  Copyright 2001-2010 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -98,6 +98,13 @@ namespace shibsp {
         virtual ~Handler();
 
         /**
+         * Returns an identifier for the protocol family associated with the handler, if any.
+         *
+         * @return  a protocol identifier, or nullptr
+         */
+        virtual const XMLCh* getProtocolFamily() const;
+
+        /**
          * Executes handler functionality as an incoming request.
          * 
          * <p>Handlers can be run either directly by incoming web requests
index e8e8b55..a2e5439 100644 (file)
@@ -158,6 +158,11 @@ Handler::~Handler()
 {
 }
 
+const XMLCh* Handler::getProtocolFamily() const
+{
+    return nullptr;
+}
+
 void Handler::log(SPRequest::SPLogLevel level, const string& msg) const
 {
     Category::getInstance(SHIBSP_LOGCAT".Handler").log(
index b35cd5c..e9176c8 100644 (file)
@@ -224,6 +224,11 @@ void AssertionConsumerService::checkAddress(const Application& application, cons
 
 #ifndef SHIBSP_LITE
 
+const XMLCh* AssertionConsumerService::getProtocolFamily() const
+{
+    return m_decoder ? m_decoder->getProtocolFamily() : nullptr;
+}
+
 const char* AssertionConsumerService::getType() const
 {
     return "AssertionConsumerService";
index 78cd49a..0470e02 100644 (file)
@@ -97,6 +97,10 @@ namespace shibsp {
 
         bool m_post;
         SecurityPolicyRule* m_ssoRule;
+#else
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML11_PROTOCOL_ENUM;
+        }
 #endif
     };
 
index 7857965..0d0cc76 100644 (file)
@@ -45,7 +45,8 @@ using namespace opensaml::saml2md;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2;
 using namespace opensaml;
-using namespace samlconstants;
+#else
+# include "lite/SAMLConstants.h"
 #endif
 
 #include <xmltooling/soap/SOAP.h>
@@ -106,6 +107,9 @@ namespace shibsp {
             role.getArtifactResolutionServices().push_back(ep);
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
 
     private:
         pair<bool,long> processMessage(const Application& application, HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
index e67297e..ce543ab 100644 (file)
@@ -45,6 +45,8 @@ using namespace opensaml;
 # ifndef min
 #  define min(a,b)            (((a) < (b)) ? (a) : (b))
 # endif
+#else
+# include "lite/SAMLConstants.h"
 #endif
 
 using namespace shibsp;
@@ -92,6 +94,10 @@ namespace shibsp {
             ) const;
 
         SecurityPolicyRule* m_ssoRule;
+#else
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
 #endif
     };
 
index 1ea0ef1..acfdd26 100644 (file)
@@ -47,6 +47,8 @@ using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
+#else
+# include "lite/SAMLConstants.h"
 #endif
 
 using namespace shibsp;
@@ -96,6 +98,9 @@ namespace shibsp {
             return "SingleLogoutService";
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
 
     private:
         pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
@@ -178,13 +183,13 @@ SAML2Logout::SAML2Logout(const DOMElement* e, const char* appId)
                     MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
                         b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
                         );
-                    if (encoder->isUserAgentPresent()) {
+                    if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                         m_encoders[start] = encoder;
                         m_log.debug("supporting outgoing binding (%s)", b.get());
                     }
                     else {
                         delete encoder;
-                        m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
                     }
                 }
                 catch (exception& ex) {
index a776bc3..66528a0 100644 (file)
@@ -80,6 +80,9 @@ namespace shibsp {
             return "LogoutInitiator";
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
 
     private:
         pair<bool,long> doRequest(
@@ -142,13 +145,13 @@ SAML2LogoutInitiator::SAML2LogoutInitiator(const DOMElement* e, const char* appI
                 auto_ptr_char b(start);
                 MessageEncoder * encoder =
                     SAMLConfig::getConfig().MessageEncoderManager.newPlugin(b.get(),pair<const DOMElement*,const XMLCh*>(e,nullptr));
-                if (encoder->isUserAgentPresent()) {
+                if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                     m_encoders[start] = encoder;
                     m_log.debug("supporting outgoing binding (%s)", b.get());
                 }
                 else {
                     delete encoder;
-                    m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
                 }
             }
             catch (exception& ex) {
index 8d0c17d..df91db9 100644 (file)
@@ -46,6 +46,8 @@ using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 using namespace opensaml;
+#else
+# include "lite/SAMLConstants.h"
 #endif
 
 using namespace shibsp;
@@ -95,6 +97,9 @@ namespace shibsp {
             return "ManageNameIDService";
         }
 #endif
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
 
     private:
         pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
@@ -174,13 +179,13 @@ SAML2NameIDMgmt::SAML2NameIDMgmt(const DOMElement* e, const char* appId)
                     MessageEncoder * encoder = conf.MessageEncoderManager.newPlugin(
                         b.get(), pair<const DOMElement*,const XMLCh*>(e,shibspconstants::SHIB2SPCONFIG_NS)
                         );
-                    if (encoder->isUserAgentPresent()) {
+                    if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                         m_encoders[start] = encoder;
                         m_log.debug("supporting outgoing binding (%s)", b.get());
                     }
                     else {
                         delete encoder;
-                        m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                        m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
                     }
                 }
                 catch (exception& ex) {
index 2765ce6..17056a2 100644 (file)
@@ -77,6 +77,10 @@ namespace shibsp {
         pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML20P_NS;
+        }
+
     private:
         pair<bool,long> doRequest(
             const Application& application,
@@ -177,13 +181,13 @@ SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* ap
                 MessageEncoder * encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
                     b.get(),pair<const DOMElement*,const XMLCh*>(e,nullptr)
                     );
-                if (encoder->isUserAgentPresent()) {
+                if (encoder->isUserAgentPresent() && XMLString::equals(getProtocolFamily(), encoder->getProtocolFamily())) {
                     m_encoders[start] = encoder;
                     m_log.debug("supporting outgoing binding (%s)", b.get());
                 }
                 else {
                     delete encoder;
-                    m_log.warn("skipping outgoing binding (%s), not a front-channel mechanism", b.get());
+                    m_log.warn("skipping outgoing binding (%s), not a SAML 2.0 front-channel mechanism", b.get());
                 }
             }
             catch (exception& ex) {
@@ -324,21 +328,9 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
     }
 
     // Validate the ACS for use with this protocol.
-    if (!ECP) {
-        pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,nullptr);
-        if (ACSbinding.first) {
-            pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
-            if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == nullptr) {
-                m_log.error("configured or requested ACS has non-SAML 2.0 binding");
-                throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
-            }
-            else if (strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST) &&
-                     strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) &&
-                     strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN)) {
-                m_log.error("configured or requested ACS has non-SAML 2.0 binding");
-                throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
-            }
-        }
+    if (!ECP && ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
+        m_log.error("configured or requested ACS has non-SAML 2.0 binding");
+        throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACS->getString("Binding").second));
     }
 
     // To invoke the request builder, the key requirement is to figure out how
index d210ff4..21a1703 100644 (file)
@@ -72,6 +72,10 @@ namespace shibsp {
         pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
         pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
 
+        const XMLCh* getProtocolFamily() const {
+            return samlconstants::SAML11_PROTOCOL_ENUM;
+        }
+
     private:
         pair<bool,long> doRequest(
             const Application& application,
@@ -158,18 +162,9 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
     }
 
     // Validate the ACS for use with this protocol.
-    pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,nullptr);
-    if (ACSbinding.first) {
-        pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
-        if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == nullptr) {
-            m_log.error("configured or requested ACS has non-SAML 1.x binding");
-            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
-        }
-        else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
-                 strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
-            m_log.error("configured or requested ACS has non-SAML 1.x binding");
-            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
-        }
+    if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
+        m_log.error("configured or requested ACS has non-SAML 1.x binding");
+        throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACS->getString("Binding").second));
     }
 
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
index b9cc9c9..160000d 100644 (file)
@@ -135,18 +135,9 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     }
 
     // Validate the ACS for use with this protocol.
-    pair<bool,const char*> ACSbinding = ACS ? ACS->getString("Binding") : pair<bool,const char*>(false,nullptr);
-    if (ACSbinding.first) {
-        pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
-        if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == nullptr) {
-            m_log.error("configured or requested ACS has non-SAML 1.x binding");
-            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
-        }
-        else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
-                 strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
-            m_log.error("configured or requested ACS has non-SAML 1.x binding");
-            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
-        }
+    if (ACS && !XMLString::equals(samlconstants::SAML11_PROTOCOL_ENUM, ACS->getProtocolFamily())) {
+        m_log.error("configured or requested ACS has non-SAML 1.x binding");
+        throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACS->getString("Binding").second));
     }
 
     if (!discoveryURL.first)
index 3942708..f885d42 100644 (file)
     <ClInclude Include="AbstractSPRequest.h" />\r
     <ClInclude Include="AccessControl.h" />\r
     <ClInclude Include="Application.h" />\r
-    <ClInclude Include="ApplicationAwarePlugin.h" />\r
     <ClInclude Include="base.h" />\r
     <ClInclude Include="exceptions.h" />\r
     <ClInclude Include="internal.h" />\r
index 9293c01..4b98a41 100644 (file)
     <ClInclude Include="Application.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="ApplicationAwarePlugin.h">\r
-      <Filter>Header Files</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="base.h">\r
       <Filter>Header Files</Filter>\r
     </ClInclude>\r