33c852cf8c9ba0bf1d90fc54be0bac44ba3e3008
[shibboleth/cpp-opensaml.git] / saml / saml2 / metadata / impl / MetadataProvider.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * MetadataProvider.cpp
23  *
24  * Supplies an individual source of metadata.
25  */
26
27 #include "internal.h"
28 #include "saml2/metadata/MetadataFilter.h"
29 #include "saml2/metadata/MetadataProvider.h"
30
31 #include <algorithm>
32 #include <boost/lambda/lambda.hpp>
33 #include <xercesc/util/XMLUniDefs.hpp>
34 #include <xmltooling/logging.h>
35 #include <xmltooling/unicode.h>
36 #include <xmltooling/util/NDC.h>
37 #include <xmltooling/util/XMLHelper.h>
38
39 using namespace opensaml::saml2md;
40 using namespace opensaml;
41 using namespace xmltooling::logging;
42 using namespace xmltooling;
43 using namespace boost::lambda;
44 using namespace boost;
45 using namespace std;
46
47 namespace opensaml {
48     namespace saml2md {
49         SAML_DLLLOCAL PluginManager<MetadataProvider,string,const DOMElement*>::Factory XMLMetadataProviderFactory;
50         SAML_DLLLOCAL PluginManager<MetadataProvider,string,const DOMElement*>::Factory DynamicMetadataProviderFactory;
51         SAML_DLLLOCAL PluginManager<MetadataProvider,string,const DOMElement*>::Factory ChainingMetadataProviderFactory;
52         SAML_DLLLOCAL PluginManager<MetadataProvider,string,const DOMElement*>::Factory FolderMetadataProviderFactory;
53         SAML_DLLLOCAL PluginManager<MetadataProvider,string,const DOMElement*>::Factory NullMetadataProviderFactory;
54         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory BlacklistMetadataFilterFactory;
55         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory WhitelistMetadataFilterFactory;
56         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory SignatureMetadataFilterFactory;
57         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory RequireValidUntilMetadataFilterFactory;
58         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory EntityRoleMetadataFilterFactory;
59         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory EntityAttributesMetadataFilterFactory;
60     };
61 };
62
63 void SAML_API opensaml::saml2md::registerMetadataProviders()
64 {
65     SAMLConfig& conf=SAMLConfig::getConfig();
66     conf.MetadataProviderManager.registerFactory(XML_METADATA_PROVIDER, XMLMetadataProviderFactory);
67     conf.MetadataProviderManager.registerFactory(DYNAMIC_METADATA_PROVIDER, DynamicMetadataProviderFactory);
68     conf.MetadataProviderManager.registerFactory(CHAINING_METADATA_PROVIDER, ChainingMetadataProviderFactory);
69     conf.MetadataProviderManager.registerFactory(FOLDER_METADATA_PROVIDER, FolderMetadataProviderFactory);
70     conf.MetadataProviderManager.registerFactory(NULL_METADATA_PROVIDER, NullMetadataProviderFactory);
71 }
72
73 void SAML_API opensaml::saml2md::registerMetadataFilters()
74 {
75     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(BLACKLIST_METADATA_FILTER, BlacklistMetadataFilterFactory);
76     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(WHITELIST_METADATA_FILTER, WhitelistMetadataFilterFactory);
77     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(SIGNATURE_METADATA_FILTER, SignatureMetadataFilterFactory);
78     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(REQUIREVALIDUNTIL_METADATA_FILTER, RequireValidUntilMetadataFilterFactory);
79     // additional name matching Java code
80     SAMLConfig::getConfig().MetadataFilterManager.registerFactory("RequiredValidUntil", RequireValidUntilMetadataFilterFactory);
81     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYROLE_METADATA_FILTER, EntityRoleMetadataFilterFactory);
82     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYATTR_METADATA_FILTER, EntityAttributesMetadataFilterFactory);
83
84 }
85
86 static const XMLCh _MetadataFilter[] =  UNICODE_LITERAL_14(M,e,t,a,d,a,t,a,F,i,l,t,e,r);
87 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);
88 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);
89 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);
90 static const XMLCh Exclude[] =          UNICODE_LITERAL_7(E,x,c,l,u,d,e);
91 static const XMLCh Include[] =          UNICODE_LITERAL_7(I,n,c,l,u,d,e);
92 static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
93
94 MetadataProvider::MetadataProvider(const DOMElement* e) : m_filterContext(nullptr)
95 {
96 #ifdef _DEBUG
97     NDC ndc("MetadataProvider");
98 #endif
99     Category& log = Category::getInstance(SAML_LOGCAT".Metadata");
100     SAMLConfig& conf = SAMLConfig::getConfig();
101
102     // Locate any default recognized filters and plugins.
103     try {
104         DOMElement* child = XMLHelper::getFirstChildElement(e);
105         while (child) {
106             if (XMLString::equals(child->getLocalName(), _MetadataFilter)) {
107                 string t = XMLHelper::getAttrString(child, nullptr, _type);
108                 if (!t.empty()) {
109                     log.info("building MetadataFilter of type %s", t.c_str());
110                     auto_ptr<MetadataFilter> np(conf.MetadataFilterManager.newPlugin(t.c_str(), child));
111                     m_filters.push_back(np.get());
112                     np.release();
113                 }
114                 else {
115                     log.error("MetadataFilter element missing type attribute");
116                 }
117             }
118             else if (XMLString::equals(child->getLocalName(), SigFilter)) {
119                 log.info("building MetadataFilter of type %s", SIGNATURE_METADATA_FILTER);
120                 m_filters.push_back(conf.MetadataFilterManager.newPlugin(SIGNATURE_METADATA_FILTER, child));
121             }
122             else if (XMLString::equals(child->getLocalName(), Whitelist)) {
123                 log.info("building MetadataFilter of type %s", WHITELIST_METADATA_FILTER);
124                 m_filters.push_back(conf.MetadataFilterManager.newPlugin(WHITELIST_METADATA_FILTER, child));
125             }
126             else if (XMLString::equals(child->getLocalName(), Blacklist)) {
127                 log.info("building MetadataFilter of type %s", BLACKLIST_METADATA_FILTER);
128                 m_filters.push_back(conf.MetadataFilterManager.newPlugin(BLACKLIST_METADATA_FILTER, child));
129             }
130             else if (XMLString::equals(child->getLocalName(), Include)) {
131                 log.info("building MetadataFilter of type %s", WHITELIST_METADATA_FILTER);
132                 m_filters.push_back(conf.MetadataFilterManager.newPlugin(WHITELIST_METADATA_FILTER, e));
133             }
134             else if (XMLString::equals(child->getLocalName(), Exclude)) {
135                 log.info("building MetadataFilter of type %s", BLACKLIST_METADATA_FILTER);
136                 m_filters.push_back(conf.MetadataFilterManager.newPlugin(BLACKLIST_METADATA_FILTER, e));
137             }
138             child = XMLHelper::getNextSiblingElement(child);
139         }
140     }
141     catch (XMLToolingException& ex) {
142         log.error("caught exception while installing filters: %s", ex.what());
143         throw;
144     }
145 }
146
147 MetadataProvider::~MetadataProvider()
148 {
149 }
150
151 const char* MetadataProvider::getId() const
152 {
153     return nullptr;
154 }
155
156 void MetadataProvider::addMetadataFilter(MetadataFilter* newFilter)
157 {
158     m_filters.push_back(newFilter);
159 }
160
161 MetadataFilter* MetadataProvider::removeMetadataFilter(MetadataFilter* oldFilter)
162 {
163     ptr_vector<MetadataFilter>::iterator i = find_if(m_filters.begin(), m_filters.end(), (&_1 == oldFilter));
164     if (i != m_filters.end()) {
165         return m_filters.release(i).release();
166     }
167     return nullptr;
168 }
169
170 void MetadataProvider::setContext(const MetadataFilterContext* ctx)
171 {
172     m_filterContext = ctx;
173 }
174
175 void MetadataProvider::doFilters(XMLObject& xmlObject) const
176 {
177     Category& log = Category::getInstance(SAML_LOGCAT".Metadata");
178     for (ptr_vector<MetadataFilter>::const_iterator i = m_filters.begin(); i != m_filters.end(); i++) {
179         log.info("applying metadata filter (%s)", i->getId());
180         i->doFilter(m_filterContext, xmlObject);
181     }
182 }
183
184 void MetadataProvider::outputStatus(ostream& os) const
185 {
186 }
187
188 const EntitiesDescriptor* MetadataProvider::getEntitiesDescriptor(const XMLCh* name, bool strict) const
189 {
190     auto_ptr_char temp(name);
191     return getEntitiesDescriptor(temp.get(),strict);
192 }
193
194 MetadataProvider::Criteria::Criteria()
195     : entityID_unicode(nullptr), entityID_ascii(nullptr), artifact(nullptr), role(nullptr), protocol(nullptr), protocol2(nullptr), validOnly(true)
196 {
197 }
198
199 MetadataProvider::Criteria::Criteria(const XMLCh* id, const xmltooling::QName* q, const XMLCh* prot, bool valid)
200     : entityID_unicode(id), entityID_ascii(nullptr), artifact(nullptr), role(q), protocol(prot), protocol2(nullptr), validOnly(valid)
201 {
202 }
203
204 MetadataProvider::Criteria::Criteria(const char* id, const xmltooling::QName* q, const XMLCh* prot, bool valid)
205     : entityID_unicode(nullptr), entityID_ascii(id), artifact(nullptr), role(q), protocol(prot), protocol2(nullptr), validOnly(valid)
206 {
207 }
208
209 MetadataProvider::Criteria::Criteria(const SAMLArtifact* a, const xmltooling::QName* q, const XMLCh* prot, bool valid)
210     : entityID_unicode(nullptr), entityID_ascii(nullptr), artifact(a), role(q), protocol(prot), protocol2(nullptr), validOnly(valid)
211 {
212 }
213
214 MetadataProvider::Criteria::~Criteria()
215 {
216 }
217
218 void MetadataProvider::Criteria::reset()
219 {
220     entityID_unicode = nullptr;
221     entityID_ascii = nullptr;
222     artifact = nullptr;
223     role = nullptr;
224     protocol = nullptr;
225     protocol2 = nullptr;
226     validOnly = true;
227 }
228
229 MetadataFilter::MetadataFilter()
230 {
231 }
232
233 MetadataFilter::~MetadataFilter()
234 {
235 }
236
237 void MetadataFilter::doFilter(const MetadataFilterContext* ctx, xmltooling::XMLObject& xmlObject) const
238 {
239     // Default call into deprecated method.
240     doFilter(xmlObject);
241 }
242
243 void MetadataFilter::doFilter(xmltooling::XMLObject& xmlObject) const
244 {
245     // Empty default for deprecated method.
246 }
247
248 MetadataFilterContext::MetadataFilterContext()
249 {
250 }
251
252 MetadataFilterContext::~MetadataFilterContext()
253 {
254 }