2 * Copyright 2001-2007 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * SignatureMetadataFilter.cpp
20 * Filters out unsigned or mis-signed elements.
24 #include "saml2/metadata/Metadata.h"
25 #include "saml2/metadata/MetadataFilter.h"
26 #include "signature/SignatureProfileValidator.h"
28 #include <log4cpp/Category.hh>
30 #include <xmltooling/security/Credential.h>
31 #include <xmltooling/security/CredentialCriteria.h>
32 #include <xmltooling/security/CredentialResolver.h>
33 #include <xmltooling/signature/SignatureValidator.h>
34 #include <xmltooling/util/NDC.h>
36 using namespace opensaml::saml2md;
37 using namespace opensaml;
38 using namespace xmlsignature;
39 using namespace xmltooling;
40 using namespace log4cpp;
46 class SAML_DLLLOCAL SignatureMetadataFilter : public MetadataFilter
49 SignatureMetadataFilter(const DOMElement* e);
50 ~SignatureMetadataFilter() {
51 delete m_credResolver;
54 const char* getId() const { return SIGNATURE_METADATA_FILTER; }
55 void doFilter(XMLObject& xmlObject) const;
58 void doFilter(EntitiesDescriptor& entities, bool rootObject=false) const;
59 void verifySignature(Signature* sig) const {
61 m_profileValidator.validate(sig);
62 m_sigValidator.validate(sig);
66 CredentialResolver* m_credResolver;
67 SignatureProfileValidator m_profileValidator;
68 mutable SignatureValidator m_sigValidator;
71 MetadataFilter* SAML_DLLLOCAL SignatureMetadataFilterFactory(const DOMElement* const & e)
73 return new SignatureMetadataFilter(e);
79 static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
80 static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e);
81 static const XMLCh certificate[] = UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e);
82 static const XMLCh Certificate[] = UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);
83 static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h);
85 SignatureMetadataFilter::SignatureMetadataFilter(const DOMElement* e) : m_credResolver(NULL)
87 if (e && e->hasAttributeNS(NULL,certificate)) {
88 // Dummy up a file resolver.
89 DOMElement* dummy = e->getOwnerDocument()->createElementNS(NULL,_CredentialResolver);
90 DOMElement* child = e->getOwnerDocument()->createElementNS(NULL,Certificate);
91 dummy->appendChild(child);
92 DOMElement* path = e->getOwnerDocument()->createElementNS(NULL,Path);
93 child->appendChild(path);
94 path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,certificate)));
95 m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(FILESYSTEM_CREDENTIAL_RESOLVER,dummy);
99 e = e ? XMLHelper::getFirstChildElement(e, _CredentialResolver) : NULL;
100 auto_ptr_char t(e ? e->getAttributeNS(NULL,type) : NULL);
102 m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(t.get(),e);
105 throw MetadataFilterException("Missing <CredentialResolver> element, or no type attribute found");
108 void SignatureMetadataFilter::doFilter(XMLObject& xmlObject) const
114 CredentialCriteria cc;
115 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
116 Locker locker(m_credResolver);
117 m_sigValidator.setCredential(m_credResolver->resolve(&cc));
120 EntitiesDescriptor& entities = dynamic_cast<EntitiesDescriptor&>(xmlObject);
121 doFilter(entities, true);
128 EntityDescriptor& entity = dynamic_cast<EntityDescriptor&>(xmlObject);
129 if (!entity.getSignature())
130 throw MetadataFilterException("Root metadata element was unsigned.");
131 verifySignature(entity.getSignature());
136 throw MetadataFilterException("SignatureMetadataFilter was given an improper metadata instance to filter.");
139 void SignatureMetadataFilter::doFilter(EntitiesDescriptor& entities, bool rootObject) const
141 Category& log=Category::getInstance(SAML_LOGCAT".Metadata");
143 Signature* sig = entities.getSignature();
144 if (!sig && rootObject)
145 throw MetadataFilterException("Root metadata element was unsigned.");
146 verifySignature(sig);
148 VectorOf(EntityDescriptor) v=entities.getEntityDescriptors();
149 for (VectorOf(EntityDescriptor)::size_type i=0; i<v.size(); ) {
151 verifySignature(v[i]->getSignature());
154 catch (XMLToolingException& e) {
155 auto_ptr_char id(v[i]->getEntityID());
156 log.info("filtering out entity (%s) after failed signature check: ", id.get(), e.what());
157 v.erase(v.begin() + i);
161 VectorOf(EntitiesDescriptor) w=entities.getEntitiesDescriptors();
162 for (VectorOf(EntitiesDescriptor)::size_type j=0; j<w.size(); ) {
164 verifySignature(w[j]->getSignature());
167 catch (XMLToolingException& e) {
168 auto_ptr_char name(w[j]->getName());
169 log.info("filtering out group (%s) after failed signature check: ", name.get(), e.what());
170 w.erase(w.begin() + j);