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 <xmltooling/logging.h>
29 #include <xmltooling/security/Credential.h>
30 #include <xmltooling/security/CredentialCriteria.h>
31 #include <xmltooling/security/CredentialResolver.h>
32 #include <xmltooling/signature/SignatureValidator.h>
33 #include <xmltooling/util/NDC.h>
35 using namespace opensaml::saml2md;
36 using namespace opensaml;
37 using namespace xmlsignature;
38 using namespace xmltooling::logging;
39 using namespace xmltooling;
45 class SAML_DLLLOCAL SignatureMetadataFilter : public MetadataFilter
48 SignatureMetadataFilter(const DOMElement* e);
49 ~SignatureMetadataFilter() {
50 delete m_credResolver;
53 const char* getId() const { return SIGNATURE_METADATA_FILTER; }
54 void doFilter(XMLObject& xmlObject) const;
57 void doFilter(EntitiesDescriptor& entities, bool rootObject=false) const;
58 void verifySignature(Signature* sig) const {
60 m_profileValidator.validate(sig);
61 m_sigValidator.validate(sig);
65 CredentialResolver* m_credResolver;
66 SignatureProfileValidator m_profileValidator;
67 mutable SignatureValidator m_sigValidator;
70 MetadataFilter* SAML_DLLLOCAL SignatureMetadataFilterFactory(const DOMElement* const & e)
72 return new SignatureMetadataFilter(e);
78 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);
79 static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e);
80 static const XMLCh certificate[] = UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e);
81 static const XMLCh Certificate[] = UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e);
82 static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h);
84 SignatureMetadataFilter::SignatureMetadataFilter(const DOMElement* e) : m_credResolver(NULL)
86 if (e && e->hasAttributeNS(NULL,certificate)) {
87 // Dummy up a file resolver.
88 DOMElement* dummy = e->getOwnerDocument()->createElementNS(NULL,_CredentialResolver);
89 DOMElement* child = e->getOwnerDocument()->createElementNS(NULL,Certificate);
90 dummy->appendChild(child);
91 DOMElement* path = e->getOwnerDocument()->createElementNS(NULL,Path);
92 child->appendChild(path);
93 path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,certificate)));
94 m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(FILESYSTEM_CREDENTIAL_RESOLVER,dummy);
98 e = e ? XMLHelper::getFirstChildElement(e, _CredentialResolver) : NULL;
99 auto_ptr_char t(e ? e->getAttributeNS(NULL,type) : NULL);
101 m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(t.get(),e);
104 throw MetadataFilterException("Missing <CredentialResolver> element, or no type attribute found");
107 void SignatureMetadataFilter::doFilter(XMLObject& xmlObject) const
113 CredentialCriteria cc;
114 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
115 Locker locker(m_credResolver);
116 m_sigValidator.setCredential(m_credResolver->resolve(&cc));
119 EntitiesDescriptor& entities = dynamic_cast<EntitiesDescriptor&>(xmlObject);
120 doFilter(entities, true);
127 EntityDescriptor& entity = dynamic_cast<EntityDescriptor&>(xmlObject);
128 if (!entity.getSignature())
129 throw MetadataFilterException("Root metadata element was unsigned.");
130 verifySignature(entity.getSignature());
135 throw MetadataFilterException("SignatureMetadataFilter was given an improper metadata instance to filter.");
138 void SignatureMetadataFilter::doFilter(EntitiesDescriptor& entities, bool rootObject) const
140 Category& log=Category::getInstance(SAML_LOGCAT".Metadata");
142 Signature* sig = entities.getSignature();
143 if (!sig && rootObject)
144 throw MetadataFilterException("Root metadata element was unsigned.");
145 verifySignature(sig);
147 VectorOf(EntityDescriptor) v=entities.getEntityDescriptors();
148 for (VectorOf(EntityDescriptor)::size_type i=0; i<v.size(); ) {
150 verifySignature(v[i]->getSignature());
153 catch (XMLToolingException& e) {
154 auto_ptr_char id(v[i]->getEntityID());
155 log.info("filtering out entity (%s) after failed signature check: ", id.get(), e.what());
156 v.erase(v.begin() + i);
160 VectorOf(EntitiesDescriptor) w=entities.getEntitiesDescriptors();
161 for (VectorOf(EntitiesDescriptor)::size_type j=0; j<w.size(); ) {
163 verifySignature(w[j]->getSignature());
166 catch (XMLToolingException& e) {
167 auto_ptr_char name(w[j]->getName());
168 log.info("filtering out group (%s) after failed signature check: ", name.get(), e.what());
169 w.erase(w.begin() + j);