Added abstract metadata base, chaining trust and metadata plugins.
authorScott Cantor <cantor.2@osu.edu>
Mon, 11 Sep 2006 02:08:40 +0000 (02:08 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 11 Sep 2006 02:08:40 +0000 (02:08 +0000)
15 files changed:
saml/Makefile.am
saml/saml.vcproj
saml/saml2/metadata/AbstractMetadataProvider.h [new file with mode: 0644]
saml/saml2/metadata/ChainingMetadataProvider.h [new file with mode: 0644]
saml/saml2/metadata/MetadataProvider.h
saml/saml2/metadata/ObservableMetadataProvider.h
saml/saml2/metadata/impl/AbstractMetadataProvider.cpp [new file with mode: 0644]
saml/saml2/metadata/impl/ChainingMetadataProvider.cpp [new file with mode: 0644]
saml/saml2/metadata/impl/FilesystemMetadataProvider.cpp
saml/saml2/metadata/impl/MetadataProvider.cpp
saml/saml2/metadata/impl/ObservableMetadataProvider.cpp
saml/security/ChainingTrustEngine.h [new file with mode: 0644]
saml/security/TrustEngine.h
saml/security/impl/ChainingTrustEngine.cpp [new file with mode: 0644]
saml/security/impl/TrustEngine.cpp

index f46e7c0..91cd7ce 100644 (file)
@@ -31,6 +31,7 @@ encinclude_HEADERS = \
 secinclude_HEADERS = \
        security/AbstractPKIXTrustEngine.h \
        security/MetadataKeyInfoIterator.h \
+       security/ChainingTrustEngine.h \
        security/TrustEngine.h \
        security/X509TrustEngine.h
 
@@ -55,7 +56,9 @@ saml2coreinclude_HEADERS = \
        saml2/core/SAML2ArtifactType0004.h
 
 saml2mdinclude_HEADERS = \
-       saml2/metadata/Metadata.h
+       saml2/metadata/AbstractMetadataProvider.h \
+       saml2/metadata/ChainingMetadataProvider.h \
+       saml2/metadata/Metadata.h \
        saml2/metadata/MetadataFilter.h \
        saml2/metadata/MetadataProvider.h \
        saml2/metadata/ObservableMetadataProvider.h
@@ -78,7 +81,9 @@ libsaml_la_SOURCES = \
        saml2/core/impl/Protocols20SchemaValidators.cpp \
        saml2/core/impl/SAML2Artifact.cpp \
        saml2/core/impl/SAML2ArtifactType0004.cpp \
+       saml2/metadata/impl/AbstractMetadataProvider.cpp \
        saml2/metadata/impl/BlacklistMetadataFilter.cpp \
+       saml2/metadata/impl/ChainingMetadataProvider.cpp \
        saml2/metadata/impl/FilesystemMetadataProvider.cpp \
        saml2/metadata/impl/MetadataImpl.cpp \
        saml2/metadata/impl/MetadataProvider.cpp \
@@ -89,6 +94,7 @@ libsaml_la_SOURCES = \
        encryption/EncryptedKeyResolver.cpp \
        security/impl/TrustEngine.cpp \
        security/impl/AbstractPKIXTrustEngine.cpp \
+       security/impl/ChainingTrustEngine.cpp \
        security/impl/ExplicitKeyTrustEngine.cpp \
        signature/ContentReference.cpp \
        signature/SignatureProfileValidator.cpp \
index 27b7e03..40d6d78 100644 (file)
                                                Name="impl"\r
                                                >\r
                                                <File\r
+                                                       RelativePath=".\saml2\metadata\impl\AbstractMetadataProvider.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\saml2\metadata\impl\BlacklistMetadataFilter.cpp"\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\saml2\metadata\impl\ChainingMetadataProvider.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\saml2\metadata\impl\FilesystemMetadataProvider.cpp"\r
                                                        >\r
                                                </File>\r
                                                >\r
                                        </File>\r
                                        <File\r
+                                               RelativePath=".\security\impl\ChainingTrustEngine.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\security\impl\ExplicitKeyTrustEngine.cpp"\r
                                                >\r
                                        </File>\r
                                        Name="metadata"\r
                                        >\r
                                        <File\r
+                                               RelativePath=".\saml2\metadata\AbstractMetadataProvider.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\saml2\metadata\ChainingMetadataProvider.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\saml2\metadata\Metadata.h"\r
                                                >\r
                                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\security\ChainingTrustEngine.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\security\MetadataKeyInfoIterator.h"\r
                                        >\r
                                </File>\r
diff --git a/saml/saml2/metadata/AbstractMetadataProvider.h b/saml/saml2/metadata/AbstractMetadataProvider.h
new file mode 100644 (file)
index 0000000..16d121b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  Copyright 2001-2006 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 saml/saml2/metadata/AbstractMetadataProvider.h
+ * 
+ * Base class for caching metadata providers.
+ */
+
+#ifndef __saml2_absmetadataprov_h__
+#define __saml2_absmetadataprov_h__
+
+#include <saml/saml2/metadata/ObservableMetadataProvider.h>
+
+namespace opensaml {
+
+    namespace saml2md {
+        
+        /**
+         * Base class for caching metadata providers.
+         */
+        class SAML_API AbstractMetadataProvider : public ObservableMetadataProvider
+        {
+        protected:
+            /**
+             * Constructor.
+             * 
+             * If a DOM is supplied, a set of default logic will be used to identify
+             * and build a KeyResolver plugin and install it into the provider.
+             * 
+             * The following XML content is supported:
+             * 
+             * <ul>
+             *  <li>&lt;KeyResolver&gt; elements with a type attribute
+             * </ul>
+             * 
+             * XML namespaces are ignored in the processing of these elements.
+             * 
+             * @param e DOM to supply configuration for provider
+             */
+            AbstractMetadataProvider(const DOMElement* e=NULL);
+            
+            void emitChangeEvent();
+            
+        public:
+            virtual ~AbstractMetadataProvider();
+            
+            virtual const xmlsignature::KeyResolver* getKeyResolver() const {
+                return m_resolver;
+            }
+            
+            virtual const EntityDescriptor* getEntityDescriptor(const char* id, bool requireValidMetadata=true) const;
+            virtual const EntityDescriptor* getEntityDescriptor(const SAMLArtifact* artifact) const;
+            virtual const EntitiesDescriptor* getEntitiesDescriptor(const char* name, bool requireValidMetadata=true) const;
+
+        protected:
+            /** Embedded KeyResolver instance. */
+            xmlsignature::KeyResolver* m_resolver;
+
+            /**
+             * Loads an entity into the cache for faster lookup. This includes
+             * processing known reverse lookup strategies for artifacts.
+             * 
+             * @param site          entity definition
+             * @param validUntil    expiration time of the entity definition
+             */
+            virtual void index(EntityDescriptor* site, time_t validUntil);
+
+            /**
+             * Loads a group of entities into the cache for faster lookup.
+             * 
+             * @param group         group definition
+             * @param validUntil    expiration time of the group definition
+             */
+            virtual void index(EntitiesDescriptor* group, time_t validUntil);
+        
+            /**
+             * Clear the cache of known entities and groups.
+             */
+            virtual void clearDescriptorIndex();
+        
+        private:
+            std::vector<MetadataFilter*> m_filters;
+
+            typedef std::multimap<std::string,const EntityDescriptor*> sitemap_t;
+            typedef std::multimap<std::string,const EntitiesDescriptor*> groupmap_t;
+            sitemap_t m_sites;
+            sitemap_t m_sources;
+            groupmap_t m_groups;
+        };
+        
+    };
+};
+
+#endif /* __saml2_absmetadataprov_h__ */
diff --git a/saml/saml2/metadata/ChainingMetadataProvider.h b/saml/saml2/metadata/ChainingMetadataProvider.h
new file mode 100644 (file)
index 0000000..d71a254
--- /dev/null
@@ -0,0 +1,101 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file saml/security/ChainingMetadataProvider.h\r
+ * \r
+ * MetadataProvider that uses multiple providers in sequence.\r
+ */\r
+\r
+#ifndef __saml_chainmeta_h__\r
+#define __saml_chainmeta_h__\r
+\r
+#include <saml/saml2/metadata/ObservableMetadataProvider.h>\r
+#include <xmltooling/util/Threads.h>\r
+\r
+namespace opensaml {\r
+    namespace saml2md {\r
+        \r
+        /**\r
+         * MetadataProvider that uses multiple providers in sequence.\r
+         */\r
+        class SAML_API ChainingMetadataProvider\r
+            : public ObservableMetadataProvider, public ObservableMetadataProvider::Observer {\r
+        public:\r
+            /**\r
+             * Constructor.\r
+             * \r
+             * If a DOM is supplied, the following XML content is supported:\r
+             * \r
+             * <ul>\r
+             *  <li>&lt;MetadataProvider&gt; elements with a type attribute\r
+             * </ul>\r
+             * \r
+             * XML namespaces are ignored in the processing of this content.\r
+             * \r
+             * @param e DOM to supply configuration for provider\r
+             */\r
+            ChainingMetadataProvider(const DOMElement* e=NULL);\r
+            \r
+            /**\r
+             * Destructor will delete any embedded engines.\r
+             */\r
+            virtual ~ChainingMetadataProvider();\r
+    \r
+            /**\r
+             * Adds a provider for future calls. The provider <strong>MUST</strong> be\r
+             * initialized before adding it. \r
+             * \r
+             * @param newProvider provider to add\r
+             */\r
+            void addMetadataProvider(MetadataProvider* newProvider) {\r
+                m_providers.push_back(newProvider);\r
+            }\r
+    \r
+            /**\r
+             * Removes a provider. The caller must delete the provider if necessary.\r
+             * \r
+             * @param oldProvider provider to remove\r
+             * @return  the old provider\r
+             */\r
+            MetadataProvider* removeMetadataProvider(MetadataProvider* oldProvider) {\r
+                for (std::vector<MetadataProvider*>::iterator i=m_providers.begin(); i!=m_providers.end(); i++) {\r
+                    if (oldProvider==(*i)) {\r
+                        m_providers.erase(i);\r
+                        return oldProvider;\r
+                    }\r
+                }\r
+                return NULL;\r
+            }\r
+\r
+            xmltooling::Lockable* lock();\r
+            void unlock();\r
+            void init();\r
+            const xmlsignature::KeyResolver* getKeyResolver() const;\r
+            const xmltooling::XMLObject* getMetadata() const;\r
+            const EntitiesDescriptor* getEntitiesDescriptor(const char* name, bool requireValidMetadata=true) const;\r
+            const EntityDescriptor* getEntityDescriptor(const char* id, bool requireValidMetadata=true) const;\r
+            const EntityDescriptor* getEntityDescriptor(const SAMLArtifact* artifact) const;\r
+            void onEvent(MetadataProvider& provider);\r
+    \r
+        private:\r
+            xmltooling::ThreadKey* m_tlsKey;\r
+            std::vector<MetadataProvider*> m_providers;\r
+        };\r
+    };    \r
+};\r
+\r
+#endif /* __saml_chainmeta_h__ */\r
index bc3f164..3a297d5 100644 (file)
@@ -54,12 +54,10 @@ namespace opensaml {
              * 
              * If a DOM is supplied, a set of default logic will be used to identify
              * and build MetadataFilter plugins and install them into the provider.
-             * A KeyResolver can also be supplied, or a default resolver will be used.
              * 
              * The following XML content is supported:
              * 
              * <ul>
-             *  <li>&lt;KeyResolver&gt; elements with a type attribute
              *  <li>&lt;MetadataFilter&gt; elements with a type attribute and type-specific content
              *  <li>&lt;Exclude&gt; elements representing a BlacklistMetadataFilter
              *  <li>&lt;BlacklistMetadataFilter&gt; element containing &lt;Exclude&gt; elements 
@@ -120,9 +118,7 @@ namespace opensaml {
              * 
              * @return an associated KeyResolver, or NULL
              */
-            virtual const xmlsignature::KeyResolver* getKeyResolver() const {
-                return m_resolver;
-            }
+            virtual const xmlsignature::KeyResolver* getKeyResolver() const=0;
             
             /**
              * Gets the entire metadata tree, after the registered filter has been applied.
@@ -154,7 +150,7 @@ namespace opensaml {
              * 
              * @return the entity's metadata or NULL if there is no metadata or no valid metadata
              */
-            virtual const EntityDescriptor* getEntityDescriptor(const char* id, bool requireValidMetadata=true) const;
+            virtual const EntityDescriptor* getEntityDescriptor(const char* id, bool requireValidMetadata=true) const=0;
 
             /**
              * Gets the metadata for an entity that issued a SAML artifact. If a valid entity is returned,
@@ -165,7 +161,7 @@ namespace opensaml {
              * 
              * @return the entity's metadata or NULL if there is no valid metadata
              */
-            virtual const EntityDescriptor* getEntityDescriptor(const SAMLArtifact* artifact) const;
+            virtual const EntityDescriptor* getEntityDescriptor(const SAMLArtifact* artifact) const=0;
 
             /**
              * Gets the metadata for a given group of entities. If a valid group is returned,
@@ -189,12 +185,9 @@ namespace opensaml {
              * 
              * @return the group's metadata or NULL if there is no metadata or no valid metadata
              */
-            virtual const EntitiesDescriptor* getEntitiesDescriptor(const char* name, bool requireValidMetadata=true) const;
+            virtual const EntitiesDescriptor* getEntitiesDescriptor(const char* name, bool requireValidMetadata=true) const=0;
 
         protected:
-            /** Embedded KeyResolver instance. */
-            xmlsignature::KeyResolver* m_resolver;
-
             /**
              * Applies any installed filters to a metadata instance.
              * 
@@ -202,36 +195,8 @@ namespace opensaml {
              */
             void doFilters(xmltooling::XMLObject& xmlObject) const;
 
-            /**
-             * Loads an entity into the cache for faster lookup. This includes
-             * processing known reverse lookup strategies for artifacts.
-             * 
-             * @param site          entity definition
-             * @param validUntil    expiration time of the entity definition
-             */
-            virtual void index(EntityDescriptor* site, time_t validUntil);
-
-            /**
-             * Loads a group of entities into the cache for faster lookup.
-             * 
-             * @param group         group definition
-             * @param validUntil    expiration time of the group definition
-             */
-            virtual void index(EntitiesDescriptor* group, time_t validUntil);
-        
-            /**
-             * Clear the cache of known entities and groups.
-             */
-            virtual void clearDescriptorIndex();
-        
         private:
             std::vector<MetadataFilter*> m_filters;
-
-            typedef std::multimap<std::string,const EntityDescriptor*> sitemap_t;
-            typedef std::multimap<std::string,const EntitiesDescriptor*> groupmap_t;
-            sitemap_t m_sites;
-            sitemap_t m_sources;
-            groupmap_t m_groups;
         };
         
         /**
@@ -241,6 +206,9 @@ namespace opensaml {
         
         /** MetadataProvider based on local XML files */
         #define FILESYSTEM_METADATA_PROVIDER  "org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider"
+
+        /** MetadataProvider that wraps a sequence of metadata providers. */
+        #define CHAINING_METADATA_PROVIDER  "org.opensaml.saml2.metadata.provider.ChainingMetadataProvider"
     };
 };
 
index e1b1ae5..3de1eb3 100644 (file)
@@ -40,12 +40,12 @@ namespace opensaml {
              * 
              * @param e DOM to supply configuration for provider
              */
-            ObservableMetadataProvider(const DOMElement* e) : MetadataProvider(e) {}
+            ObservableMetadataProvider(const DOMElement* e=NULL) : MetadataProvider(e) {}
             
             /**
              * Convenience method for notifying every registered Observer of an event.
              */
-            void emitChangeEvent();
+            virtual void emitChangeEvent();
 
         public:
             /**
diff --git a/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp b/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp
new file mode 100644 (file)
index 0000000..59e4303
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  Copyright 2001-2006 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.
+ */
+
+/**
+ * AbstractMetadataProvider.cpp
+ * 
+ * Base class for caching metadata providers.
+ */
+
+#include "internal.h"
+#include "SAMLArtifact.h"
+#include "saml2/metadata/Metadata.h"
+#include "saml2/metadata/AbstractMetadataProvider.h"
+
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/signature/CachingKeyResolver.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+static const XMLCh GenericKeyResolver[] =           UNICODE_LITERAL_11(K,e,y,R,e,s,o,l,v,e,r);
+static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);
+
+AbstractMetadataProvider::AbstractMetadataProvider(const DOMElement* e) : ObservableMetadataProvider(e), m_resolver(NULL)
+{
+    e = e ? XMLHelper::getFirstChildElement(e, GenericKeyResolver) : NULL;
+    if (e) {
+        auto_ptr_char t(e->getAttributeNS(NULL,type));
+        if (t.get())
+            m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),e);
+        else
+            throw UnknownExtensionException("<KeyResolver> element found with no type attribute");
+    }
+    
+    if (!m_resolver) {
+        m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER, NULL);
+    }
+}
+
+AbstractMetadataProvider::~AbstractMetadataProvider()
+{
+    delete m_resolver;
+}
+
+void AbstractMetadataProvider::emitChangeEvent()
+{
+    xmlsignature::CachingKeyResolver* ckr=dynamic_cast<xmlsignature::CachingKeyResolver*>(m_resolver);
+    if (ckr)
+        ckr->clearCache();
+    ObservableMetadataProvider::emitChangeEvent();    
+}
+
+void AbstractMetadataProvider::index(EntityDescriptor* site, time_t validUntil)
+{
+    if (validUntil < site->getValidUntilEpoch())
+        site->setValidUntil(validUntil);
+
+    auto_ptr_char id(site->getEntityID());
+    if (id.get()) {
+        m_sites.insert(make_pair(id.get(),site));
+    }
+    
+    // Process each IdP role.
+    const vector<IDPSSODescriptor*>& roles=const_cast<const EntityDescriptor*>(site)->getIDPSSODescriptors();
+    for (vector<IDPSSODescriptor*>::const_iterator i=roles.begin(); i!=roles.end(); i++) {
+        // SAML 1.x?
+        if ((*i)->hasSupport(SAMLConstants::SAML10_PROTOCOL_ENUM) || (*i)->hasSupport(SAMLConstants::SAML11_PROTOCOL_ENUM)) {
+            // Check for SourceID extension element.
+            const Extensions* exts=(*i)->getExtensions();
+            if (exts) {
+                const list<XMLObject*>& children=exts->getXMLObjects();
+                for (list<XMLObject*>::const_iterator ext=children.begin(); ext!=children.end(); ext++) {
+                    SourceID* sid=dynamic_cast<SourceID*>(*ext);
+                    if (sid) {
+                        auto_ptr_char sourceid(sid->getID());
+                        if (sourceid.get()) {
+                            m_sources.insert(pair<string,const EntityDescriptor*>(sourceid.get(),site));
+                            break;
+                        }
+                    }
+                }
+            }
+            
+            // Hash the ID.
+            m_sources.insert(
+                pair<string,const EntityDescriptor*>(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)
+                );
+                
+            // Load endpoints for type 0x0002 artifacts.
+            const vector<ArtifactResolutionService*>& locs=const_cast<const IDPSSODescriptor*>(*i)->getArtifactResolutionServices();
+            for (vector<ArtifactResolutionService*>::const_iterator loc=locs.begin(); loc!=locs.end(); loc++) {
+                auto_ptr_char location((*loc)->getLocation());
+                if (location.get())
+                    m_sources.insert(pair<string,const EntityDescriptor*>(location.get(),site));
+            }
+        }
+        
+        // SAML 2.0?
+        if ((*i)->hasSupport(SAMLConstants::SAML20P_NS)) {
+            // Hash the ID.
+            m_sources.insert(
+                pair<string,const EntityDescriptor*>(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)
+                );
+        }
+    }
+}
+
+void AbstractMetadataProvider::index(EntitiesDescriptor* group, time_t validUntil)
+{
+    if (validUntil < group->getValidUntilEpoch())
+        group->setValidUntil(validUntil);
+
+    auto_ptr_char name(group->getName());
+    if (name.get()) {
+        m_groups.insert(make_pair(name.get(),group));
+    }
+    
+    const vector<EntitiesDescriptor*>& groups=const_cast<const EntitiesDescriptor*>(group)->getEntitiesDescriptors();
+    for (vector<EntitiesDescriptor*>::const_iterator i=groups.begin(); i!=groups.end(); i++)
+        index(*i,group->getValidUntilEpoch());
+
+    const vector<EntityDescriptor*>& sites=const_cast<const EntitiesDescriptor*>(group)->getEntityDescriptors();
+    for (vector<EntityDescriptor*>::const_iterator j=sites.begin(); j!=sites.end(); j++)
+        index(*j,group->getValidUntilEpoch());
+}
+
+void AbstractMetadataProvider::clearDescriptorIndex()
+{
+    m_sources.clear();
+    m_sites.clear();
+    m_groups.clear();
+}
+
+const EntitiesDescriptor* AbstractMetadataProvider::getEntitiesDescriptor(const char* name, bool strict) const
+{
+    pair<groupmap_t::const_iterator,groupmap_t::const_iterator> range=m_groups.equal_range(name);
+
+    time_t now=time(NULL);
+    for (groupmap_t::const_iterator i=range.first; i!=range.second; i++)
+        if (now < i->second->getValidUntilEpoch())
+            return i->second;
+    
+    if (!strict && range.first!=range.second)
+        return range.first->second;
+        
+    return NULL;
+}
+
+const EntityDescriptor* AbstractMetadataProvider::getEntityDescriptor(const char* name, bool strict) const
+{
+    pair<sitemap_t::const_iterator,sitemap_t::const_iterator> range=m_sites.equal_range(name);
+
+    time_t now=time(NULL);
+    for (sitemap_t::const_iterator i=range.first; i!=range.second; i++)
+        if (now < i->second->getValidUntilEpoch())
+            return i->second;
+    
+    if (!strict && range.first!=range.second)
+        return range.first->second;
+        
+    return NULL;
+}
+
+const EntityDescriptor* AbstractMetadataProvider::getEntityDescriptor(const SAMLArtifact* artifact) const
+{
+    pair<sitemap_t::const_iterator,sitemap_t::const_iterator> range=m_sources.equal_range(artifact->getSource());
+
+    time_t now=time(NULL);
+    for (sitemap_t::const_iterator i=range.first; i!=range.second; i++)
+        if (now < i->second->getValidUntilEpoch())
+            return i->second;
+
+    return NULL;
+}
diff --git a/saml/saml2/metadata/impl/ChainingMetadataProvider.cpp b/saml/saml2/metadata/impl/ChainingMetadataProvider.cpp
new file mode 100644 (file)
index 0000000..7f410d2
--- /dev/null
@@ -0,0 +1,176 @@
+/*\r
+ *  Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ChainingMetadataProvider.cpp\r
+ * \r
+ * MetadataProvider that uses multiple providers in sequence.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "saml2/metadata/ChainingMetadataProvider.h"\r
+\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+using namespace xmlsignature;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace opensaml {\r
+    namespace saml2md {\r
+        MetadataProvider* SAML_DLLLOCAL ChainingMetadataProviderFactory(const DOMElement* const & e)\r
+        {\r
+            return new ChainingMetadataProvider(e);\r
+        }\r
+    };\r
+};\r
+\r
+static const XMLCh GenericMetadataProvider[] =      UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);\r
+static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);\r
+\r
+ChainingMetadataProvider::ChainingMetadataProvider(const DOMElement* e) : ObservableMetadataProvider(e), m_tlsKey(NULL)\r
+{\r
+    try {\r
+        e = e ? xmltooling::XMLHelper::getFirstChildElement(e, GenericMetadataProvider) : NULL;\r
+        while (e) {\r
+            auto_ptr_char temp(e->getAttributeNS(NULL,type));\r
+            if (temp.get()) {\r
+                auto_ptr<MetadataProvider> provider(\r
+                    SAMLConfig::getConfig().MetadataProviderManager.newPlugin(temp.get(), e)\r
+                    );\r
+                ObservableMetadataProvider* obs = dynamic_cast<ObservableMetadataProvider*>(provider.get());\r
+                if (obs)\r
+                    obs->addObserver(this);\r
+                m_providers.push_back(provider.get());\r
+                provider.release();\r
+            }\r
+            e = XMLHelper::getNextSiblingElement(e, GenericMetadataProvider);\r
+        }\r
+    }\r
+    catch (XMLToolingException&) {\r
+        for_each(m_providers.begin(), m_providers.end(), xmltooling::cleanup<MetadataProvider>());\r
+        throw;\r
+    }\r
+    m_tlsKey = ThreadKey::create(NULL);\r
+}\r
+\r
+ChainingMetadataProvider::~ChainingMetadataProvider()\r
+{\r
+    delete m_tlsKey;\r
+    for_each(m_providers.begin(), m_providers.end(), xmltooling::cleanup<MetadataProvider>());\r
+}\r
+\r
+void ChainingMetadataProvider::onEvent(MetadataProvider& provider)\r
+{\r
+    emitChangeEvent();\r
+}\r
+\r
+void ChainingMetadataProvider::init()\r
+{\r
+    for_each(m_providers.begin(), m_providers.end(), mem_fun<void,MetadataProvider>(&MetadataProvider::init));\r
+}\r
+\r
+Lockable* ChainingMetadataProvider::lock()\r
+{\r
+    return this;   // we're not lockable ourselves...\r
+}\r
+\r
+void ChainingMetadataProvider::unlock()\r
+{\r
+    // Check for a locked provider.\r
+    void* ptr=m_tlsKey->getData();\r
+    if (ptr) {\r
+        m_tlsKey->setData(NULL);\r
+        reinterpret_cast<MetadataProvider*>(ptr)->unlock();\r
+    }\r
+}\r
+\r
+const KeyResolver* ChainingMetadataProvider::getKeyResolver() const\r
+{\r
+    // Check for a locked provider.\r
+    void* ptr=m_tlsKey->getData();\r
+    return ptr ? reinterpret_cast<MetadataProvider*>(ptr)->getKeyResolver() : NULL;\r
+    \r
+}\r
+\r
+const XMLObject* ChainingMetadataProvider::getMetadata() const\r
+{\r
+    throw XMLToolingException("getMetadata operation not implemented on this provider.");\r
+}\r
+\r
+const EntitiesDescriptor* ChainingMetadataProvider::getEntitiesDescriptor(const char* name, bool requireValidMetadata) const\r
+{\r
+    // Clear any existing lock.\r
+    const_cast<ChainingMetadataProvider*>(this)->unlock();\r
+\r
+    // Do a search.\r
+    const EntitiesDescriptor* ret=NULL;\r
+    for (vector<MetadataProvider*>::const_iterator i=m_providers.begin(); i!=m_providers.end(); ++i) {\r
+        (*i)->lock();\r
+        if (ret=(*i)->getEntitiesDescriptor(name,requireValidMetadata)) {\r
+            // Save locked provider.\r
+            m_tlsKey->setData(*i);\r
+            return ret;\r
+        }\r
+        (*i)->unlock();\r
+    }\r
+\r
+    return NULL;\r
+}\r
+\r
+const EntityDescriptor* ChainingMetadataProvider::getEntityDescriptor(const char* id, bool requireValidMetadata) const\r
+{\r
+    // Clear any existing lock.\r
+    const_cast<ChainingMetadataProvider*>(this)->unlock();\r
+\r
+    // Do a search.\r
+    const EntityDescriptor* ret=NULL;\r
+    for (vector<MetadataProvider*>::const_iterator i=m_providers.begin(); i!=m_providers.end(); ++i) {\r
+        (*i)->lock();\r
+        if (ret=(*i)->getEntityDescriptor(id,requireValidMetadata)) {\r
+            // Save locked provider.\r
+            m_tlsKey->setData(*i);\r
+            return ret;\r
+        }\r
+        (*i)->unlock();\r
+    }\r
+\r
+    return NULL;\r
+}\r
+\r
+const EntityDescriptor* ChainingMetadataProvider::getEntityDescriptor(const SAMLArtifact* artifact) const\r
+{\r
+    // Clear any existing lock.\r
+    const_cast<ChainingMetadataProvider*>(this)->unlock();\r
+\r
+    // Do a search.\r
+    const EntityDescriptor* ret=NULL;\r
+    for (vector<MetadataProvider*>::const_iterator i=m_providers.begin(); i!=m_providers.end(); ++i) {\r
+        (*i)->lock();\r
+        if (ret=(*i)->getEntityDescriptor(artifact)) {\r
+            // Save locked provider.\r
+            m_tlsKey->setData(*i);\r
+            return ret;\r
+        }\r
+        (*i)->unlock();\r
+    }\r
+\r
+    return NULL;\r
+}\r
index c5b210e..8651747 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "saml2/metadata/Metadata.h"
-#include "saml2/metadata/ObservableMetadataProvider.h"
+#include "saml2/metadata/AbstractMetadataProvider.h"
 
 #include <ctime>
 #include <sys/types.h>
@@ -44,7 +44,7 @@ namespace opensaml {
     namespace saml2md {
         
         
-        class SAML_DLLLOCAL FilesystemMetadataProvider : public ObservableMetadataProvider
+        class SAML_DLLLOCAL FilesystemMetadataProvider : public AbstractMetadataProvider
         {
         public:
             FilesystemMetadataProvider(const DOMElement* e);
@@ -91,7 +91,7 @@ static const XMLCh filename[] = UNICODE_LITERAL_8(f,i,l,e,n,a,m,e);
 static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
 
 FilesystemMetadataProvider::FilesystemMetadataProvider(const DOMElement* e)
-    : ObservableMetadataProvider(e), m_root(e), m_filestamp(0), m_validate(false), m_lock(NULL), m_object(NULL)
+    : AbstractMetadataProvider(e), m_root(e), m_filestamp(0), m_validate(false), m_lock(NULL), m_object(NULL)
 {
 #ifdef _DEBUG
     NDC ndc("FilesystemMetadataProvider");
@@ -257,9 +257,9 @@ void FilesystemMetadataProvider::index()
     clearDescriptorIndex();
     EntitiesDescriptor* group=dynamic_cast<EntitiesDescriptor*>(m_object);
     if (group) {
-        MetadataProvider::index(group, SAMLTIME_MAX);
+        AbstractMetadataProvider::index(group, SAMLTIME_MAX);
         return;
     }
     EntityDescriptor* site=dynamic_cast<EntityDescriptor*>(m_object);
-    MetadataProvider::index(site, SAMLTIME_MAX);
+    AbstractMetadataProvider::index(site, SAMLTIME_MAX);
 }
index fc5d7de..8c01e62 100644 (file)
@@ -21,8 +21,6 @@
  */
 
 #include "internal.h"
-#include "SAMLArtifact.h"
-#include "saml2/metadata/Metadata.h"
 #include "saml2/metadata/MetadataProvider.h"
 
 #include <log4cpp/Category.hh>
@@ -38,10 +36,11 @@ using namespace std;
 
 namespace opensaml {
     namespace saml2md {
-        SAML_DLLLOCAL PluginManager<MetadataProvider,const DOMElement*>::Factory FilesystemMetadataProviderFactory; 
-        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory BlacklistMetadataFilterFactory; 
-        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory WhitelistMetadataFilterFactory; 
-        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory SignatureMetadataFilterFactory; 
+        SAML_DLLLOCAL PluginManager<MetadataProvider,const DOMElement*>::Factory FilesystemMetadataProviderFactory;
+        SAML_DLLLOCAL PluginManager<MetadataProvider,const DOMElement*>::Factory ChainingMetadataProviderFactory;
+        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory BlacklistMetadataFilterFactory;
+        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory WhitelistMetadataFilterFactory;
+        SAML_DLLLOCAL PluginManager<MetadataFilter,const DOMElement*>::Factory SignatureMetadataFilterFactory;
     };
 };
 
@@ -49,6 +48,7 @@ void SAML_API opensaml::saml2md::registerMetadataProviders()
 {
     SAMLConfig& conf=SAMLConfig::getConfig();
     conf.MetadataProviderManager.registerFactory(FILESYSTEM_METADATA_PROVIDER, FilesystemMetadataProviderFactory);
+    conf.MetadataProviderManager.registerFactory(CHAINING_METADATA_PROVIDER, ChainingMetadataProviderFactory);
     conf.MetadataProviderManager.registerFactory("edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadata", FilesystemMetadataProviderFactory);
     conf.MetadataProviderManager.registerFactory("edu.internet2.middleware.shibboleth.common.provider.XMLMetadata", FilesystemMetadataProviderFactory);
 }
@@ -65,11 +65,10 @@ static const XMLCh Whitelist[] =                    UNICODE_LITERAL_23(W,h,i,t,e
 static const XMLCh SigFilter[] =                    UNICODE_LITERAL_23(S,i,g,n,a,t,u,r,e,M,e,t,a,d,a,t,a,F,i,l,t,e,r);
 static const XMLCh Exclude[] =                      UNICODE_LITERAL_7(E,x,c,l,u,d,e);
 static const XMLCh Include[] =                      UNICODE_LITERAL_7(I,n,c,l,u,d,e);
-static const XMLCh GenericKeyResolver[] =           UNICODE_LITERAL_11(K,e,y,R,e,s,o,l,v,e,r);
 static const XMLCh GenericMetadataFilter[] =        UNICODE_LITERAL_14(M,e,t,a,d,a,t,a,F,i,l,t,e,r);
 static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);
 
-MetadataProvider::MetadataProvider(const DOMElement* e) : m_resolver(NULL)
+MetadataProvider::MetadataProvider(const DOMElement* e)
 {
 #ifdef _DEBUG
     NDC ndc("MetadataProvider");
@@ -80,14 +79,7 @@ MetadataProvider::MetadataProvider(const DOMElement* e) : m_resolver(NULL)
     try {
         DOMElement* child = e ? XMLHelper::getFirstChildElement(e) : NULL;
         while (child) {
-            if (!m_resolver && XMLString::equals(child->getLocalName(),GenericKeyResolver)) {
-                auto_ptr_char t(child->getAttributeNS(NULL,type));
-                if (t.get())
-                    m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),child);
-                else
-                    throw UnknownExtensionException("<KeyResolver> element found with no type attribute");
-            }
-            else if (XMLString::equals(child->getLocalName(),GenericMetadataFilter)) {
+            if (XMLString::equals(child->getLocalName(),GenericMetadataFilter)) {
                 auto_ptr_char t(child->getAttributeNS(NULL,type));
                 if (t.get())
                     m_filters.push_back(conf.MetadataFilterManager.newPlugin(t.get(),child));
@@ -111,14 +103,9 @@ MetadataProvider::MetadataProvider(const DOMElement* e) : m_resolver(NULL)
             }
             child = XMLHelper::getNextSiblingElement(child);
         }
-        
-        if (!m_resolver) {
-            m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER, child);
-        }
     }
     catch (XMLToolingException& ex) {
-        Category::getInstance(SAML_LOGCAT".Metadata").error("caught exception while installing plugins and filters: %s", ex.what());
-        delete m_resolver;
+        Category::getInstance(SAML_LOGCAT".Metadata").error("caught exception while installing filters: %s", ex.what());
         for_each(m_filters.begin(),m_filters.end(),xmltooling::cleanup<MetadataFilter>());
         throw;
     }
@@ -126,7 +113,6 @@ MetadataProvider::MetadataProvider(const DOMElement* e) : m_resolver(NULL)
 
 MetadataProvider::~MetadataProvider()
 {
-    delete m_resolver;
     for_each(m_filters.begin(),m_filters.end(),xmltooling::cleanup<MetadataFilter>());
 }
 
@@ -142,137 +128,14 @@ void MetadataProvider::doFilters(XMLObject& xmlObject) const
     }
 }
 
-void MetadataProvider::index(EntityDescriptor* site, time_t validUntil)
-{
-    if (validUntil < site->getValidUntilEpoch())
-        site->setValidUntil(validUntil);
-
-    auto_ptr_char id(site->getEntityID());
-    if (id.get()) {
-        m_sites.insert(make_pair(id.get(),site));
-    }
-    
-    // Process each IdP role.
-    const vector<IDPSSODescriptor*>& roles=const_cast<const EntityDescriptor*>(site)->getIDPSSODescriptors();
-    for (vector<IDPSSODescriptor*>::const_iterator i=roles.begin(); i!=roles.end(); i++) {
-        // SAML 1.x?
-        if ((*i)->hasSupport(SAMLConstants::SAML10_PROTOCOL_ENUM) || (*i)->hasSupport(SAMLConstants::SAML11_PROTOCOL_ENUM)) {
-            // Check for SourceID extension element.
-            const Extensions* exts=(*i)->getExtensions();
-            if (exts) {
-                const list<XMLObject*>& children=exts->getXMLObjects();
-                for (list<XMLObject*>::const_iterator ext=children.begin(); ext!=children.end(); ext++) {
-                    SourceID* sid=dynamic_cast<SourceID*>(*ext);
-                    if (sid) {
-                        auto_ptr_char sourceid(sid->getID());
-                        if (sourceid.get()) {
-                            m_sources.insert(pair<string,const EntityDescriptor*>(sourceid.get(),site));
-                            break;
-                        }
-                    }
-                }
-            }
-            
-            // Hash the ID.
-            m_sources.insert(
-                pair<string,const EntityDescriptor*>(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)
-                );
-                
-            // Load endpoints for type 0x0002 artifacts.
-            const vector<ArtifactResolutionService*>& locs=const_cast<const IDPSSODescriptor*>(*i)->getArtifactResolutionServices();
-            for (vector<ArtifactResolutionService*>::const_iterator loc=locs.begin(); loc!=locs.end(); loc++) {
-                auto_ptr_char location((*loc)->getLocation());
-                if (location.get())
-                    m_sources.insert(pair<string,const EntityDescriptor*>(location.get(),site));
-            }
-        }
-        
-        // SAML 2.0?
-        if ((*i)->hasSupport(SAMLConstants::SAML20P_NS)) {
-            // Hash the ID.
-            m_sources.insert(
-                pair<string,const EntityDescriptor*>(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)
-                );
-        }
-    }
-}
-
-void MetadataProvider::index(EntitiesDescriptor* group, time_t validUntil)
-{
-    if (validUntil < group->getValidUntilEpoch())
-        group->setValidUntil(validUntil);
-
-    auto_ptr_char name(group->getName());
-    if (name.get()) {
-        m_groups.insert(make_pair(name.get(),group));
-    }
-    
-    const vector<EntitiesDescriptor*>& groups=const_cast<const EntitiesDescriptor*>(group)->getEntitiesDescriptors();
-    for (vector<EntitiesDescriptor*>::const_iterator i=groups.begin(); i!=groups.end(); i++)
-        index(*i,group->getValidUntilEpoch());
-
-    const vector<EntityDescriptor*>& sites=const_cast<const EntitiesDescriptor*>(group)->getEntityDescriptors();
-    for (vector<EntityDescriptor*>::const_iterator j=sites.begin(); j!=sites.end(); j++)
-        index(*j,group->getValidUntilEpoch());
-}
-
-void MetadataProvider::clearDescriptorIndex()
-{
-    m_sources.clear();
-    m_sites.clear();
-    m_groups.clear();
-}
-
-const EntitiesDescriptor* MetadataProvider::getEntitiesDescriptor(const char* name, bool strict) const
-{
-    pair<groupmap_t::const_iterator,groupmap_t::const_iterator> range=m_groups.equal_range(name);
-
-    time_t now=time(NULL);
-    for (groupmap_t::const_iterator i=range.first; i!=range.second; i++)
-        if (now < i->second->getValidUntilEpoch())
-            return i->second;
-    
-    if (!strict && range.first!=range.second)
-        return range.first->second;
-        
-    return NULL;
-}
-
 const EntitiesDescriptor* MetadataProvider::getEntitiesDescriptor(const XMLCh* name, bool strict) const
 {
     auto_ptr_char temp(name);
     return getEntitiesDescriptor(temp.get(),strict);
 }
 
-const EntityDescriptor* MetadataProvider::getEntityDescriptor(const char* name, bool strict) const
-{
-    pair<sitemap_t::const_iterator,sitemap_t::const_iterator> range=m_sites.equal_range(name);
-
-    time_t now=time(NULL);
-    for (sitemap_t::const_iterator i=range.first; i!=range.second; i++)
-        if (now < i->second->getValidUntilEpoch())
-            return i->second;
-    
-    if (!strict && range.first!=range.second)
-        return range.first->second;
-        
-    return NULL;
-}
-
 const EntityDescriptor* MetadataProvider::getEntityDescriptor(const XMLCh* name, bool strict) const
 {
     auto_ptr_char temp(name);
     return getEntityDescriptor(temp.get(),strict);
 }
-
-const EntityDescriptor* MetadataProvider::getEntityDescriptor(const SAMLArtifact* artifact) const
-{
-    pair<sitemap_t::const_iterator,sitemap_t::const_iterator> range=m_sources.equal_range(artifact->getSource());
-
-    time_t now=time(NULL);
-    for (sitemap_t::const_iterator i=range.first; i!=range.second; i++)
-        if (now < i->second->getValidUntilEpoch())
-            return i->second;
-
-    return NULL;
-}
index 069a1e2..569c030 100644 (file)
@@ -23,8 +23,6 @@
 #include "internal.h"
 #include "saml2/metadata/ObservableMetadataProvider.h"
 
-#include <xmltooling/signature/CachingKeyResolver.h>
-
 using namespace opensaml::saml2md;
 using namespace std;
 
@@ -35,10 +33,6 @@ ObservableMetadataProvider::~ObservableMetadataProvider()
 
 void ObservableMetadataProvider::emitChangeEvent()
 {
-    xmlsignature::CachingKeyResolver* ckr=dynamic_cast<xmlsignature::CachingKeyResolver*>(m_resolver);
-    if (ckr)
-        ckr->clearCache();
-    
     for (std::vector<Observer*>::const_iterator i=m_observers.begin(); i!=m_observers.end(); i++) {
         (*i)->onEvent(*this);
     }
diff --git a/saml/security/ChainingTrustEngine.h b/saml/security/ChainingTrustEngine.h
new file mode 100644 (file)
index 0000000..9e80dc5
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file saml/security/ChainingTrustEngine.h\r
+ * \r
+ * X509TrustEngine that uses multiple engines in sequence.\r
+ */\r
+\r
+#ifndef __saml_chaintrust_h__\r
+#define __saml_chaintrust_h__\r
+\r
+#include <saml/security/X509TrustEngine.h>\r
+\r
+namespace opensaml {\r
+\r
+    /**\r
+     * X509TrustEngine that uses multiple engines in sequence.\r
+     */\r
+    class SAML_API ChainingTrustEngine : public X509TrustEngine {\r
+    public:\r
+        /**\r
+         * Constructor.\r
+         * \r
+         * If a DOM is supplied, the following XML content is supported:\r
+         * \r
+         * <ul>\r
+         *  <li>&lt;TrustEngine&gt; elements with a type attribute\r
+         * </ul>\r
+         * \r
+         * XML namespaces are ignored in the processing of this content.\r
+         * \r
+         * @param e DOM to supply configuration for provider\r
+         */\r
+        ChainingTrustEngine(const DOMElement* e=NULL);\r
+        \r
+        /**\r
+         * Destructor will delete any embedded engines.\r
+         */\r
+        virtual ~ChainingTrustEngine();\r
+\r
+        /**\r
+         * Adds a trust engine for future calls.\r
+         * \r
+         * @param newEngine trust engine to add\r
+         */\r
+        void addTrustEngine(X509TrustEngine* newEngine) {\r
+            m_engines.push_back(newEngine);\r
+        }\r
+\r
+        /**\r
+         * Removes a trust engine. The caller must delete the engine if necessary.\r
+         * \r
+         * @param oldEngine trust engine to remove\r
+         * @return  the old engine\r
+         */\r
+        X509TrustEngine* removeTrustEngine(X509TrustEngine* oldEngine) {\r
+            for (std::vector<X509TrustEngine*>::iterator i=m_engines.begin(); i!=m_engines.end(); i++) {\r
+                if (oldEngine==(*i)) {\r
+                    m_engines.erase(i);\r
+                    return oldEngine;\r
+                }\r
+            }\r
+            return NULL;\r
+        }\r
+\r
+        virtual bool validate(\r
+            xmlsignature::Signature& sig,\r
+            const saml2md::RoleDescriptor& role,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            );\r
+        virtual bool validate(\r
+            XSECCryptoX509* certEE,\r
+            const std::vector<XSECCryptoX509*>& certChain,\r
+            const saml2md::RoleDescriptor& role,\r
+            bool checkName=true,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            );\r
+\r
+    private:\r
+        std::vector<X509TrustEngine*> m_engines;\r
+    };\r
+    \r
+};\r
+\r
+#endif /* __saml_chaintrust_h__ */\r
index 0cc211f..e07774d 100644 (file)
@@ -81,6 +81,9 @@ namespace opensaml {
 \r
     /** TrustEngine based on explicit key information resolved from metadata. */\r
     #define EXPLICIT_KEY_SAMLTRUSTENGINE  "org.opensaml.security.ExplicitKeyTrustEngine"\r
+\r
+    /** TrustEngine that tries multiple engines in sequence. */\r
+    #define CHAINING_SAMLTRUSTENGINE  "org.opensaml.security.ChainingTrustEngine"\r
 };\r
 \r
 #endif /* __saml_trust_h__ */\r
diff --git a/saml/security/impl/ChainingTrustEngine.cpp b/saml/security/impl/ChainingTrustEngine.cpp
new file mode 100644 (file)
index 0000000..ef8634b
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ *  Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ChainingTrustEngine.cpp\r
+ * \r
+ * TrustEngine that uses multiple engines in sequence.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "security/ChainingTrustEngine.h"\r
+\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+using namespace xmlsignature;\r
+using namespace std;\r
+\r
+namespace opensaml {\r
+    TrustEngine* SAML_DLLLOCAL ChainingTrustEngineFactory(const DOMElement* const & e)\r
+    {\r
+        return new ChainingTrustEngine(e);\r
+    }\r
+};\r
+\r
+static const XMLCh GenericTrustEngine[] =           UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);\r
+static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);\r
+\r
+ChainingTrustEngine::ChainingTrustEngine(const DOMElement* e) {\r
+    try {\r
+        e = e ? xmltooling::XMLHelper::getFirstChildElement(e, GenericTrustEngine) : NULL;\r
+        while (e) {\r
+            xmltooling::auto_ptr_char temp(e->getAttributeNS(NULL,type));\r
+            if (temp.get()) {\r
+                auto_ptr<TrustEngine> engine(\r
+                    SAMLConfig::getConfig().TrustEngineManager.newPlugin(temp.get(), e)\r
+                    );\r
+                X509TrustEngine* x509 = dynamic_cast<X509TrustEngine*>(engine.get());\r
+                if (x509) {\r
+                    m_engines.push_back(x509);\r
+                    engine.release();\r
+                }\r
+                else {\r
+                    throw xmltooling::UnknownExtensionException("Embedded trust engine does not support required interface.");\r
+                }\r
+            }\r
+            e = xmltooling::XMLHelper::getNextSiblingElement(e, GenericTrustEngine);\r
+        }\r
+    }\r
+    catch (xmltooling::XMLToolingException&) {\r
+        for_each(m_engines.begin(), m_engines.end(), xmltooling::cleanup<X509TrustEngine>());\r
+        throw;\r
+    }\r
+}\r
+\r
+ChainingTrustEngine::~ChainingTrustEngine() {\r
+    for_each(m_engines.begin(), m_engines.end(), xmltooling::cleanup<X509TrustEngine>());\r
+}\r
+\r
+bool ChainingTrustEngine::validate(\r
+    Signature& sig,\r
+    const RoleDescriptor& role,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+    for (vector<X509TrustEngine*>::iterator i=m_engines.begin(); i!=m_engines.end(); ++i) {\r
+        if (static_cast<TrustEngine*>(*i)->validate(sig,role,keyResolver))\r
+            return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+bool ChainingTrustEngine::validate(\r
+    XSECCryptoX509* certEE,\r
+    const vector<XSECCryptoX509*>& certChain,\r
+    const RoleDescriptor& role,\r
+    bool checkName,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+    for (vector<X509TrustEngine*>::iterator i=m_engines.begin(); i!=m_engines.end(); ++i) {\r
+        if ((*i)->validate(certEE,certChain,role,checkName,keyResolver))\r
+            return true;\r
+    }\r
+    return false;\r
+}\r
index f5084c2..e33f4b0 100644 (file)
@@ -29,10 +29,12 @@ using namespace std;
 
 namespace opensaml {
     SAML_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory ExplicitKeyTrustEngineFactory; 
+    SAML_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory ChainingTrustEngineFactory;
 };
 
 void SAML_API opensaml::registerTrustEngines()
 {
     SAMLConfig& conf=SAMLConfig::getConfig();
     conf.TrustEngineManager.registerFactory(EXPLICIT_KEY_SAMLTRUSTENGINE, ExplicitKeyTrustEngineFactory);
+    conf.TrustEngineManager.registerFactory(CHAINING_SAMLTRUSTENGINE, ChainingTrustEngineFactory);
 }