-/*
- * Copyright 2001-2010 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
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you 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
+ * 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.
+ * 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.
*/
/**
#include "saml2/metadata/MetadataCredentialContext.h"
#include "saml2/metadata/MetadataCredentialCriteria.h"
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/if.hpp>
+#include <boost/lambda/lambda.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/security/Credential.h>
#include <xmltooling/security/KeyInfoResolver.h>
#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/util/DateTime.h>
#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
using namespace opensaml::saml2md;
using namespace xmltooling::logging;
using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
using namespace std;
using opensaml::SAMLArtifact;
static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);
-static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e);
+static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
AbstractMetadataProvider::AbstractMetadataProvider(const DOMElement* e)
- : ObservableMetadataProvider(e), m_resolver(nullptr), m_credentialLock(nullptr)
+ : ObservableMetadataProvider(e), m_lastUpdate(0), m_resolver(nullptr), m_credentialLock(Mutex::create())
{
- e = e ? XMLHelper::getFirstChildElement(e, _KeyInfoResolver) : nullptr;
+ e = XMLHelper::getFirstChildElement(e, _KeyInfoResolver);
if (e) {
- auto_ptr_char t(e->getAttributeNS(nullptr,type));
- if (t.get())
- m_resolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(),e);
- else
+ string t = XMLHelper::getAttrString(e, nullptr, _type);
+ if (!t.empty()) {
+ m_resolverWrapper.reset(XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.c_str(), e));
+ m_resolver = m_resolverWrapper.get();
+ }
+ else {
throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
+ }
}
- m_credentialLock = Mutex::create();
}
AbstractMetadataProvider::~AbstractMetadataProvider()
{
for (credmap_t::iterator c = m_credentialMap.begin(); c!=m_credentialMap.end(); ++c)
for_each(c->second.begin(), c->second.end(), xmltooling::cleanup<Credential>());
- delete m_credentialLock;
- delete m_resolver;
+}
+
+void AbstractMetadataProvider::outputStatus(ostream& os) const
+{
+ os << "<MetadataProvider";
+
+ if (getId() && *getId()) {
+ os << " id='" << getId() << "'";
+ }
+
+ if (m_lastUpdate > 0) {
+ DateTime ts(m_lastUpdate);
+ ts.parseDateTime();
+ auto_ptr_char timestamp(ts.getFormattedString());
+ os << " lastUpdate='" << timestamp.get() << "'";
+ }
+
+ os << "/>";
}
void AbstractMetadataProvider::emitChangeEvent() const
ObservableMetadataProvider::emitChangeEvent();
}
+void AbstractMetadataProvider::emitChangeEvent(const EntityDescriptor& entity) const
+{
+ for (credmap_t::iterator c = m_credentialMap.begin(); c!=m_credentialMap.end(); ++c)
+ for_each(c->second.begin(), c->second.end(), xmltooling::cleanup<Credential>());
+ m_credentialMap.clear();
+ ObservableMetadataProvider::emitChangeEvent(entity);
+}
+
void AbstractMetadataProvider::indexEntity(EntityDescriptor* site, time_t& validUntil, bool replace) const
{
// If child expires later than input, reset child, otherwise lower input to match.
auto_ptr_char id(site->getEntityID());
if (id.get()) {
if (replace) {
- m_sites.erase(id.get());
+ // The data structure here needs work.
+ // We have to find all the sites stored against the replaced ID. Then we have to
+ // search for those sites in the entire set of sites tracked by the sources map and
+ // remove them from both places.
+ set<const EntityDescriptor*> existingSites;
+ pair<sitemap_t::iterator,sitemap_t::iterator> existingRange = m_sites.equal_range(id.get());
+ static pair<set<const EntityDescriptor*>::iterator,bool> (set<const EntityDescriptor*>::* ins)(const EntityDescriptor* const &) =
+ &set<const EntityDescriptor*>::insert;
+ for_each(
+ existingRange.first, existingRange.second,
+ lambda::bind(ins, boost::ref(existingSites), lambda::bind(&sitemap_t::value_type::second, _1))
+ );
+ m_sites.erase(existingRange.first, existingRange.second);
for (sitemap_t::iterator s = m_sources.begin(); s != m_sources.end();) {
- if (s->second == site) {
+ if (existingSites.count(s->second) > 0) {
sitemap_t::iterator temp = s;
++s;
m_sources.erase(temp);
return i->second;
if (range.first != range.second) {
- Category& log = Category::getInstance(SAML_LOGCAT".MetadataProvider");
+ Category& log = Category::getInstance(SAML_LOGCAT ".MetadataProvider");
if (strict) {
log.warn("ignored expired metadata group (%s)", range.first->first.c_str());
}
}
if (!result.first && range.first!=range.second) {
- Category& log = Category::getInstance(SAML_LOGCAT".MetadataProvider");
+ Category& log = Category::getInstance(SAML_LOGCAT ".MetadataProvider");
if (criteria.validOnly) {
log.warn("ignored expired metadata instance for (%s)", range.first->first.c_str());
}
const credmap_t::mapped_type& creds = resolveCredentials(metacrit->getRole());
for (credmap_t::mapped_type::const_iterator c = creds.begin(); c!=creds.end(); ++c)
- if (metacrit->matches(*(*c)))
- return *c;
- return nullptr;
+ if (metacrit->matches(*(*c)))
+ return *c;
+return nullptr;
}
vector<const Credential*>::size_type AbstractMetadataProvider::resolve(
Lock lock(m_credentialLock);
const credmap_t::mapped_type& creds = resolveCredentials(metacrit->getRole());
- for (credmap_t::mapped_type::const_iterator c = creds.begin(); c!=creds.end(); ++c)
- if (metacrit->matches(*(*c)))
- results.push_back(*c);
+ for (credmap_t::mapped_type::const_iterator c = creds.begin(); c!=creds.end(); ++c)
+ if (metacrit->matches(*(*c)))
+ results.push_back(*c);
return results.size();
}
const AbstractMetadataProvider::credmap_t::mapped_type& AbstractMetadataProvider::resolveCredentials(const RoleDescriptor& role) const
{
credmap_t::const_iterator i = m_credentialMap.find(&role);
- if (i!=m_credentialMap.end())
+ if (i != m_credentialMap.end())
return i->second;
const KeyInfoResolver* resolver = m_resolver ? m_resolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
const vector<KeyDescriptor*>& keys = role.getKeyDescriptors();
AbstractMetadataProvider::credmap_t::mapped_type& resolved = m_credentialMap[&role];
- for (vector<KeyDescriptor*>::const_iterator k = keys.begin(); k!=keys.end(); ++k) {
- if ((*k)->getKeyInfo()) {
- auto_ptr<MetadataCredentialContext> mcc(new MetadataCredentialContext(*(*k)));
- Credential* c = resolver->resolve(mcc.get());
- mcc.release();
- resolved.push_back(c);
+ for (indirect_iterator<vector<KeyDescriptor*>::const_iterator> k = make_indirect_iterator(keys.begin());
+ k != make_indirect_iterator(keys.end()); ++k) {
+ if (k->getKeyInfo()) {
+ auto_ptr<MetadataCredentialContext> mcc(new MetadataCredentialContext(*k));
+ auto_ptr<Credential> c(resolver->resolve(mcc.get()));
+ if (c.get()) {
+ mcc.release(); // this API sucks, the object is now owned by the Credential
+ resolved.push_back(c.get());
+ c.release();
+ }
}
}
return resolved;