secinclude_HEADERS = \
security/AbstractPKIXTrustEngine.h \
security/MetadataKeyInfoIterator.h \
+ security/ChainingTrustEngine.h \
security/TrustEngine.h \
security/X509TrustEngine.h
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
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 \
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 \
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
--- /dev/null
+/*
+ * 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><KeyResolver> 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__ */
--- /dev/null
+/*\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><MetadataProvider> 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
*
* 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><KeyResolver> elements with a type attribute
* <li><MetadataFilter> elements with a type attribute and type-specific content
* <li><Exclude> elements representing a BlacklistMetadataFilter
* <li><BlacklistMetadataFilter> element containing <Exclude> elements
*
* @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.
*
* @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,
*
* @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,
*
* @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.
*
*/
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;
};
/**
/** 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"
};
};
*
* @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:
/**
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*\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
#include "internal.h"
#include "saml2/metadata/Metadata.h"
-#include "saml2/metadata/ObservableMetadataProvider.h"
+#include "saml2/metadata/AbstractMetadataProvider.h"
#include <ctime>
#include <sys/types.h>
namespace saml2md {
- class SAML_DLLLOCAL FilesystemMetadataProvider : public ObservableMetadataProvider
+ class SAML_DLLLOCAL FilesystemMetadataProvider : public AbstractMetadataProvider
{
public:
FilesystemMetadataProvider(const DOMElement* 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");
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);
}
*/
#include "internal.h"
-#include "SAMLArtifact.h"
-#include "saml2/metadata/Metadata.h"
#include "saml2/metadata/MetadataProvider.h"
#include <log4cpp/Category.hh>
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;
};
};
{
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);
}
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");
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));
}
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;
}
MetadataProvider::~MetadataProvider()
{
- delete m_resolver;
for_each(m_filters.begin(),m_filters.end(),xmltooling::cleanup<MetadataFilter>());
}
}
}
-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;
-}
#include "internal.h"
#include "saml2/metadata/ObservableMetadataProvider.h"
-#include <xmltooling/signature/CachingKeyResolver.h>
-
using namespace opensaml::saml2md;
using namespace std;
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);
}
--- /dev/null
+/*\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><TrustEngine> 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
\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
--- /dev/null
+/*\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
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);
}