Implement artifact resolution support.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 2 Apr 2007 03:56:10 +0000 (03:56 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 2 Apr 2007 03:56:10 +0000 (03:56 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2210 cb58f699-b61c-0410-a6fe-9272a202ed29

shibsp/Makefile.am
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/binding/ArtifactResolver.h [new file with mode: 0644]
shibsp/binding/SOAPClient.h
shibsp/binding/impl/ArtifactResolver.cpp [new file with mode: 0644]
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/shibsp.vcproj

index aef97dc..88f50e4 100644 (file)
@@ -50,6 +50,7 @@ attrresinclude_HEADERS = \
        attribute/resolver/ResolutionContext.h
 
 bindinclude_HEADERS = \
+       binding/ArtifactResolver.h \
        binding/SOAPClient.h
 
 handinclude_HEADERS = \
@@ -91,6 +92,7 @@ libshibsp_la_SOURCES = \
        attribute/ScopedAttributeDecoder.cpp \
        attribute/resolver/impl/AttributeResolver.cpp \
        attribute/resolver/impl/SimpleAttributeResolver.cpp \
+       binding/impl/ArtifactResolver.cpp \
        binding/impl/SOAPClient.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
index ff635ab..3b6940a 100644 (file)
@@ -30,6 +30,7 @@
 #include "SPConfig.h"
 #include "attribute/AttributeDecoder.h"
 #include "attribute/resolver/AttributeResolver.h"
+#include "binding/ArtifactResolver.h"
 #include "handler/Handler.h"
 #include "metadata/MetadataExt.h"
 #include "remoting/ListenerService.h"
@@ -114,6 +115,9 @@ bool SPInternalConfig::init(const char* catalog_path)
     registerRequestMappers();
     registerSessionCaches();
     registerServiceProviders();
+
+    if (isEnabled(OutOfProcess))
+        m_artifactResolver = new ArtifactResolver();
     
     log.info("library initialization complete");
     return true;
@@ -127,8 +131,8 @@ void SPInternalConfig::term()
     Category& log=Category::getInstance(SHIBSP_LOGCAT".Config");
     log.info("shutting down the library");
 
-    delete m_serviceProvider;
-    m_serviceProvider = NULL;
+    setServiceProvider(NULL);
+    setArtifactResolver(NULL);
 
     AssertionConsumerServiceManager.deregisterFactories();
     ManageNameIDServiceManager.deregisterFactories();
index 917abdb..dfcd19c 100644 (file)
@@ -24,6 +24,7 @@
 #define __shibsp_config_h__
 
 #include <shibsp/base.h>
+#include <saml/binding/MessageDecoder.h>
 #include <xmltooling/PluginManager.h>
 #include <xercesc/dom/DOM.hpp>
 
@@ -135,6 +136,28 @@ namespace shibsp {
             return m_serviceProvider;
         }
 
+        /**
+         * Sets the global ArtifactResolver instance.
+         *
+         * <p>This method must be externally synchronized with any code that uses the object.
+         * Any previously set object is destroyed.
+         * 
+         * @param artifactResolver   new ArtifactResolver instance to store
+         */
+        void setArtifactResolver(opensaml::MessageDecoder::ArtifactResolver* artifactResolver) {
+            delete m_artifactResolver;
+            m_artifactResolver = artifactResolver;
+        }
+        
+        /**
+         * Returns the global ArtifactResolver instance.
+         * 
+         * @return  global ArtifactResolver or NULL
+         */
+        opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const {
+            return m_artifactResolver;
+        }
+
         /** Separator for serialized values of multi-valued attributes. */
         char attribute_value_delimeter;
         
@@ -199,11 +222,14 @@ namespace shibsp {
         xmltooling::PluginManager< Handler,std::pair<const xercesc::DOMElement*,const char*> > SingleLogoutServiceManager;
 
     protected:
-        SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL), m_features(0) {}
+        SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL), m_artifactResolver(NULL), m_features(0) {}
         
         /** Global ServiceProvider instance. */
         ServiceProvider* m_serviceProvider;
 
+        /** Global ArtifactResolver instance. */
+        opensaml::MessageDecoder::ArtifactResolver* m_artifactResolver;
+
     private:
         unsigned long m_features;
     };
diff --git a/shibsp/binding/ArtifactResolver.h b/shibsp/binding/ArtifactResolver.h
new file mode 100644 (file)
index 0000000..7f89680
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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/binding/ArtifactResolver.h
+ * 
+ * SAML artifact resolver for SP use.
+ */
+
+#ifndef __shibsp_artres_h__
+#define __shibsp_artres_h__
+
+#include <shibsp/base.h>
+#include <saml/binding/MessageDecoder.h>
+
+namespace shibsp {
+
+    /**
+     * SAML artifact resolver for SP use.
+     */
+    class SHIBSP_API ArtifactResolver : public opensaml::MessageDecoder::ArtifactResolver {
+    public:
+        ArtifactResolver() {}
+        virtual ~ArtifactResolver() {}
+
+        opensaml::saml1p::Response* resolve(
+            const std::vector<opensaml::SAMLArtifact*>& artifacts,
+            const opensaml::saml2md::IDPSSODescriptor& idpDescriptor,
+            opensaml::SecurityPolicy& policy
+            ) const;
+
+        opensaml::saml2p::ArtifactResponse* resolve(
+            const opensaml::saml2p::SAML2Artifact& artifact,
+            const opensaml::saml2md::SSODescriptorType& ssoDescriptor,
+            opensaml::SecurityPolicy& policy
+            ) const;
+    };
+};
+
+#endif /* __shibsp_artres_h__ */
index 4f18061..70c7b1f 100644 (file)
@@ -29,6 +29,8 @@
 
 namespace shibsp {
 
+    class SHIBSP_API PropertySet;
+
     /**
      * Specialized SOAPClient for SP environment.
      */
diff --git a/shibsp/binding/impl/ArtifactResolver.cpp b/shibsp/binding/impl/ArtifactResolver.cpp
new file mode 100644 (file)
index 0000000..3f85c48
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *  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.
+ */
+
+/**
+ * ArtifactResolver.cpp
+ * 
+ * SAML artifact resolver for SP use.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "exceptions.h"
+#include "binding/ArtifactResolver.h"
+#include "binding/SOAPClient.h"
+#include "security/SecurityPolicy.h"
+
+#include <saml/saml1/core/Protocols.h>
+#include <saml/saml1/binding/SAML1SOAPClient.h>
+#include <saml/saml2/core/Protocols.h>
+#include <saml/saml2/binding/SAML2Artifact.h>
+#include <saml/saml2/binding/SAML2SOAPClient.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/util/SAMLConstants.h>
+
+#include <log4cpp/Category.hh>
+
+using namespace shibsp;
+using namespace opensaml::saml1p;
+using namespace opensaml::saml2;
+using namespace opensaml::saml2p;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace log4cpp;
+using namespace xmltooling;
+using namespace std;
+
+saml1p::Response* ArtifactResolver::resolve(
+    const vector<SAMLArtifact*>& artifacts,
+    const IDPSSODescriptor& idpDescriptor,
+    opensaml::SecurityPolicy& policy
+    ) const
+{
+    MetadataCredentialCriteria mcc(idpDescriptor);
+    shibsp::SOAPClient soaper(dynamic_cast<shibsp::SecurityPolicy&>(policy));
+
+    auto_ptr_XMLCh binding(samlconstants::SAML1_BINDING_SOAP);
+    saml1p::Response* response=NULL;
+    const vector<ArtifactResolutionService*>& endpoints=idpDescriptor.getArtifactResolutionServices();
+    for (vector<ArtifactResolutionService*>::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) {
+        try {
+            if (!XMLString::equals((*ep)->getBinding(),binding.get()))
+                continue;
+            auto_ptr_char loc((*ep)->getLocation());
+            saml1p::Request* request = saml1p::RequestBuilder::buildRequest();
+            request->setMinorVersion(idpDescriptor.hasSupport(samlconstants::SAML11_PROTOCOL_ENUM) ? 1 : 0);
+            for (vector<SAMLArtifact*>::const_iterator a = artifacts.begin(); a!=artifacts.end(); ++a) {
+                auto_ptr_XMLCh artbuf((*a)->encode().c_str());
+                AssertionArtifact* aa = AssertionArtifactBuilder::buildAssertionArtifact();
+                aa->setArtifact(artbuf.get());
+                request->getAssertionArtifacts().push_back(aa);
+            }
+
+            SAML1SOAPClient client(soaper);
+            client.sendSAML(request, mcc, loc.get());
+            response = client.receiveSAML();
+        }
+        catch (exception& ex) {
+            Category::getInstance(SHIBSP_LOGCAT".ArtifactResolver").error("exception resolving SAML 1.x artifact(s): %s", ex.what());
+            soaper.reset();
+        }
+    }
+
+    if (!response)
+        throw BindingException("Unable to successfully resolve artifact(s).");
+    return response;
+}
+
+ArtifactResponse* ArtifactResolver::resolve(
+    const SAML2Artifact& artifact,
+    const SSODescriptorType& ssoDescriptor,
+    opensaml::SecurityPolicy& policy
+    ) const
+{
+    MetadataCredentialCriteria mcc(ssoDescriptor);
+    shibsp::SecurityPolicy& sppolicy = dynamic_cast<shibsp::SecurityPolicy&>(policy);
+    shibsp::SOAPClient soaper(sppolicy);
+
+    auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
+    ArtifactResponse* response=NULL;
+    const vector<ArtifactResolutionService*>& endpoints=ssoDescriptor.getArtifactResolutionServices();
+    for (vector<ArtifactResolutionService*>::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) {
+        try {
+            if (!XMLString::equals((*ep)->getBinding(),binding.get()))
+                continue;
+            auto_ptr_char loc((*ep)->getLocation());
+            auto_ptr_XMLCh issuer(sppolicy.getApplication().getString("providerId").second);
+            ArtifactResolve* request = ArtifactResolveBuilder::buildArtifactResolve();
+            Issuer* iss = IssuerBuilder::buildIssuer();
+            request->setIssuer(iss);
+            iss->setName(issuer.get());
+            auto_ptr_XMLCh artbuf(artifact.encode().c_str());
+            Artifact* a = ArtifactBuilder::buildArtifact();
+            a->setArtifact(artbuf.get());
+            request->setArtifact(a);
+
+            SAML2SOAPClient client(soaper);
+            client.sendSAML(request, mcc, loc.get());
+            StatusResponseType* srt = client.receiveSAML();
+            if (!(response = dynamic_cast<ArtifactResponse*>(srt))) {
+                delete srt;
+                break;
+            }
+        }
+        catch (exception& ex) {
+            Category::getInstance(SHIBSP_LOGCAT".ArtifactResolver").error("exception resolving SAML 2.0 artifact: %s", ex.what());
+            soaper.reset();
+        }
+    }
+
+    if (!response)
+        throw BindingException("Unable to successfully resolve artifact.");
+    return response;
+}
index 829208b..e664fc9 100644 (file)
@@ -49,8 +49,10 @@ AssertionConsumerService::AssertionConsumerService(const DOMElement* e, const ch
     address += getString("Location").second;
     address += "::run::ACS";
     setAddress(address.c_str());
-    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
+    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
         m_decoder = SAMLConfig::getConfig().MessageDecoderManager.newPlugin(getString("Binding").second,e);
+        m_decoder->setArtifactResolver(SPConfig::getConfig().getArtifactResolver());
+    }
 }
 
 AssertionConsumerService::~AssertionConsumerService()
index b987060..eceb68d 100644 (file)
                                        Name="impl"\r
                                        >\r
                                        <File\r
+                                               RelativePath=".\binding\impl\ArtifactResolver.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\binding\impl\SOAPClient.cpp"\r
                                                >\r
                                        </File>\r
                                Name="binding"\r
                                >\r
                                <File\r
+                                       RelativePath=".\binding\ArtifactResolver.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\binding\SOAPClient.h"\r
                                        >\r
                                </File>\r