saml2/metadata/impl/MetadataProvider.cpp \
saml2/metadata/impl/MetadataSchemaValidators.cpp \
saml2/metadata/impl/ObservableMetadataProvider.cpp \
+ saml2/metadata/impl/SignatureMetadataFilter.cpp \
saml2/metadata/impl/WhitelistMetadataFilter.cpp \
signature/ContentReference.cpp \
signature/SignatureProfileValidator.cpp \
>\r
</File>\r
<File\r
+ RelativePath=".\saml2\metadata\impl\SignatureMetadataFilter.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\saml2\metadata\impl\WhitelistMetadataFilter.cpp"\r
>\r
</File>\r
/** MetadataFilter that deletes all but whitelisted entities. */
#define WHITELIST_METADATA_FILTER "org.opensaml.saml2.metadata.provider.WhitelistMetadataFilter"
+
+ /** MetadataFilter that verifies signatures and filters out any that don't pass. */
+ #define SIGNATURE_METADATA_FILTER "org.opensaml.saml2.metadata.provider.SignatureMetadataFilter"
DECL_XMLTOOLING_EXCEPTION(MetadataFilterException,SAML_EXCEPTIONAPI(SAML_API),opensaml::saml2md,xmltooling::XMLToolingException,Exceptions related to metadata filtering);
};
*
* <ul>
* <li><KeyResolver> elements with a type attribute
- * <li><MetadataFilter> 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
* <li><Include> elements representing a WhitelistMetadataFilter
+ * <li><SignatureMetadataFilter> element containing a <KeyResolver> element
* <li><WhitelistMetadataFilter> element containing <Include> elements
* </ul>
*
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;
};
};
{
SAMLConfig::getConfig().MetadataFilterManager.registerFactory(BLACKLIST_METADATA_FILTER, BlacklistMetadataFilterFactory);
SAMLConfig::getConfig().MetadataFilterManager.registerFactory(WHITELIST_METADATA_FILTER, WhitelistMetadataFilterFactory);
+ SAMLConfig::getConfig().MetadataFilterManager.registerFactory(SIGNATURE_METADATA_FILTER, SignatureMetadataFilterFactory);
}
static const XMLCh Blacklist[] = UNICODE_LITERAL_23(B,l,a,c,k,l,i,s,t,M,e,t,a,d,a,t,a,F,i,l,t,e,r);
static const XMLCh Whitelist[] = UNICODE_LITERAL_23(W,h,i,t,e,l,i,s,t,M,e,t,a,d,a,t,a,F,i,l,t,e,r);
+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);
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)) {
auto_ptr_char t(child->getAttributeNS(NULL,type));
if (t.get())
m_filters.push_back(conf.MetadataFilterManager.newPlugin(t.get(),child));
+ else
+ throw UnknownExtensionException("<MetadataFilter> element found with no type attribute");
+ }
+ else if (XMLString::equals(child->getLocalName(),SigFilter)) {
+ m_filters.push_back(conf.MetadataFilterManager.newPlugin(SIGNATURE_METADATA_FILTER,child));
}
else if (XMLString::equals(child->getLocalName(),Whitelist)) {
m_filters.push_back(conf.MetadataFilterManager.newPlugin(WHITELIST_METADATA_FILTER,child));
--- /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.
+ */
+
+/**
+ * BlacklistMetadataFilter.cpp
+ *
+ * Removes blacklisted entities from a metadata instance
+ */
+
+#include "internal.h"
+#include "saml2/metadata/MetadataFilter.h"
+#include "signature/SignatureProfileValidator.h"
+
+#include <log4cpp/Category.hh>
+
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/signature/SignatureValidator.h>
+
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+ namespace saml2md {
+
+ class SAML_DLLLOCAL SignatureMetadataFilter : public MetadataFilter
+ {
+ public:
+ SignatureMetadataFilter(const DOMElement* e);
+ ~SignatureMetadataFilter() {
+ delete m_sigValidator;
+ }
+
+ const char* getId() const { return SIGNATURE_METADATA_FILTER; }
+ void doFilter(XMLObject& xmlObject) const;
+
+ private:
+ void doFilter(EntitiesDescriptor& entities, bool rootObject=false) const;
+ void verifySignature(Signature* sig) const {
+ if (sig) {
+ m_profileValidator.validate(sig);
+ m_sigValidator->validate(sig);
+ }
+ }
+
+ SignatureProfileValidator m_profileValidator;
+ SignatureValidator* m_sigValidator;
+ };
+
+ MetadataFilter* SAML_DLLLOCAL SignatureMetadataFilterFactory(const DOMElement* const & e)
+ {
+ return new SignatureMetadataFilter(e);
+ }
+
+ };
+};
+
+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);
+
+SignatureMetadataFilter::SignatureMetadataFilter(const DOMElement* e) : m_sigValidator(NULL)
+{
+ e = XMLHelper::getFirstChildElement(e, GenericKeyResolver);
+ auto_ptr_char t(e ? e->getAttributeNS(NULL,type) : NULL);
+ if (t.get()) {
+ auto_ptr<KeyResolver> kr(XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),e));
+ m_sigValidator = new SignatureValidator(kr.get());
+ kr.release();
+ }
+ else
+ throw MetadataFilterException("missing <KeyResolver> element, or no type attribute found");
+}
+
+void SignatureMetadataFilter::doFilter(XMLObject& xmlObject) const
+{
+#ifdef _DEBUG
+ NDC ndc("doFilter");
+#endif
+
+ try {
+ EntitiesDescriptor& entities = dynamic_cast<EntitiesDescriptor&>(xmlObject);
+ doFilter(entities, true);
+ return;
+ }
+ catch (bad_cast) {
+ }
+
+ try {
+ EntityDescriptor& entity = dynamic_cast<EntityDescriptor&>(xmlObject);
+ if (!entity.getSignature())
+ throw MetadataFilterException("Root metadata element was unsigned.");
+ verifySignature(entity.getSignature());
+ }
+ catch (bad_cast) {
+ }
+
+ throw MetadataFilterException("SignatureMetadataFilter was given an improper metadata instance to filter.");
+}
+
+void SignatureMetadataFilter::doFilter(EntitiesDescriptor& entities, bool rootObject) const
+{
+ Category& log=Category::getInstance(SAML_LOGCAT".Metadata");
+
+ Signature* sig = entities.getSignature();
+ if (!sig && rootObject)
+ throw MetadataFilterException("Root metadata element was unsigned.");
+ verifySignature(sig);
+
+ VectorOf(EntityDescriptor) v=entities.getEntityDescriptors();
+ for (VectorOf(EntityDescriptor)::size_type i=0; i<v.size(); ) {
+ try {
+ verifySignature(v[i]->getSignature());
+ i++;
+ }
+ catch (XMLToolingException& e) {
+ auto_ptr_char id(v[i]->getEntityID());
+ log.info("filtering out entity (%s) after failed signature check: ", id.get(), e.what());
+ v.erase(v.begin() + i);
+ }
+ }
+
+ VectorOf(EntitiesDescriptor) w=entities.getEntitiesDescriptors();
+ for (VectorOf(EntitiesDescriptor)::size_type j=0; j<w.size(); ) {
+ try {
+ verifySignature(w[j]->getSignature());
+ j++;
+ }
+ catch (XMLToolingException& e) {
+ auto_ptr_char name(w[j]->getName());
+ log.info("filtering out group (%s) after failed signature check: ", name.get(), e.what());
+ w.erase(w.begin() + j);
+ }
+ }
+}
<?xml version="1.0" encoding="UTF-8"?>
-<FilesystemMetadataProvider path="../samltest/data/saml2/metadata/InCommon-metadata.xml" validate="0"/>
+<FilesystemMetadataProvider path="../samltest/data/saml2/metadata/InCommon-metadata.xml" validate="0">
+ <SignatureMetadataFilter>
+ <KeyResolver type="org.opensaml.xmlooling.InlineKeyResolver"/>
+ </SignatureMetadataFilter>
+</FilesystemMetadataProvider>
}
}
- void assertEquals(const char* failMessage, DOMDocument* expectedDOM, XMLObject* xmlObject) {
- DOMElement* generatedDOM = xmlObject->marshall();
+ void assertEquals(const char* failMessage, DOMDocument* expectedDOM, XMLObject* xmlObject, bool canMarshall=true) {
+ DOMElement* generatedDOM = xmlObject->getDOM();
+ if (!generatedDOM) {
+ if (!canMarshall) {
+ TSM_ASSERT("DOM not available", false);
+ }
+ else {
+ generatedDOM = xmlObject->marshall();
+ }
+ }
if (!generatedDOM->isEqualNode(expectedDOM->getDocumentElement())) {
string buf;
XMLHelper::serialize(generatedDOM, buf);
}
}
- void assertEquals(DOMDocument* expectedDOM, XMLObject* xmlObject) {
- assertEquals("Marshalled DOM was not the same as the expected DOM", expectedDOM, xmlObject);
+ void assertEquals(DOMDocument* expectedDOM, XMLObject* xmlObject, bool canMarshall=true) {
+ assertEquals("Marshalled DOM was not the same as the expected DOM", expectedDOM, xmlObject, canMarshall);
delete xmlObject;
}
auto_ptr<MetadataProvider> metadataProvider(\r
SAMLConfig::getConfig().MetadataProviderManager.newPlugin(FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement())\r
);\r
- metadataProvider->init();\r
+ try {\r
+ metadataProvider->init();\r
+ }\r
+ catch (XMLToolingException& ex) {\r
+ TS_TRACE(ex.what());\r
+ throw;\r
+ }\r
\r
-\r
Locker locker(metadataProvider.get());\r
const EntityDescriptor* descriptor = metadataProvider->getEntityDescriptor(entityID);\r
TSM_ASSERT("Retrieved entity descriptor was null", descriptor!=NULL);\r
auto_ptr<MetadataProvider> metadataProvider(\r
SAMLConfig::getConfig().MetadataProviderManager.newPlugin(FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement())\r
);\r
- metadataProvider->init();\r
- \r
+ try {\r
+ metadataProvider->init();\r
+ }\r
+ catch (XMLToolingException& ex) {\r
+ TS_TRACE(ex.what());\r
+ throw;\r
+ }\r
\r
Locker locker(metadataProvider.get());\r
const EntityDescriptor* descriptor = metadataProvider->getEntityDescriptor(entityID);\r
auto_ptr<MetadataProvider> metadataProvider(\r
SAMLConfig::getConfig().MetadataProviderManager.newPlugin(FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement())\r
);\r
- metadataProvider->init();\r
- \r
+ try {\r
+ metadataProvider->init();\r
+ }\r
+ catch (XMLToolingException& ex) {\r
+ TS_TRACE(ex.what());\r
+ throw;\r
+ }\r
\r
Locker locker(metadataProvider.get());\r
const EntityDescriptor* descriptor = metadataProvider->getEntityDescriptor(entityID2);\r