X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=saml%2Fsaml2%2Fmetadata%2Fimpl%2FAbstractMetadataProvider.cpp;h=2852bb6ff5d518a3d59afdeab825728f91da505b;hb=c072b75e6f6e05e24a1c35b952008b38d0d375c1;hp=aad86ed9c566500026b6aa5160048933359b95b2;hpb=58dfaa3ab3e5e09af7a643e58aedbc961884accb;p=shibboleth%2Fcpp-opensaml.git diff --git a/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp b/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp index aad86ed..2852bb6 100644 --- a/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp +++ b/saml/saml2/metadata/impl/AbstractMetadataProvider.cpp @@ -24,56 +24,73 @@ #include "binding/SAMLArtifact.h" #include "saml2/metadata/Metadata.h" #include "saml2/metadata/AbstractMetadataProvider.h" +#include "saml2/metadata/MetadataCredentialContext.h" +#include "saml2/metadata/MetadataCredentialCriteria.h" #include -#include +#include +#include #include using namespace opensaml::saml2md; -using namespace opensaml; using namespace xmltooling; using namespace std; +using opensaml::SAMLArtifact; -static const XMLCh _KeyResolver[] = 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); +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); -AbstractMetadataProvider::AbstractMetadataProvider(const DOMElement* e) : ObservableMetadataProvider(e), m_resolver(NULL) +AbstractMetadataProvider::AbstractMetadataProvider(const DOMElement* e) + : ObservableMetadataProvider(e), m_resolver(NULL), m_credentialLock(NULL) { - e = e ? XMLHelper::getFirstChildElement(e, _KeyResolver) : NULL; + e = e ? XMLHelper::getFirstChildElement(e, _KeyInfoResolver) : NULL; if (e) { auto_ptr_char t(e->getAttributeNS(NULL,type)); if (t.get()) - m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),e); + m_resolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(),e); else - throw UnknownExtensionException(" element found with no type attribute"); - } - - if (!m_resolver) { - m_resolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER, NULL); + throw UnknownExtensionException(" 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()); + delete m_credentialLock; delete m_resolver; } -void AbstractMetadataProvider::emitChangeEvent() +void AbstractMetadataProvider::emitChangeEvent() const { - CachingKeyResolver* ckr=dynamic_cast(m_resolver); - if (ckr) - ckr->clearCache(); - ObservableMetadataProvider::emitChangeEvent(); + for (credmap_t::iterator c = m_credentialMap.begin(); c!=m_credentialMap.end(); ++c) + for_each(c->second.begin(), c->second.end(), xmltooling::cleanup()); + m_credentialMap.clear(); + ObservableMetadataProvider::emitChangeEvent(); } -void AbstractMetadataProvider::index(EntityDescriptor* site, time_t validUntil) +void AbstractMetadataProvider::index(EntityDescriptor* site, time_t validUntil, bool replace) const { if (validUntil < site->getValidUntilEpoch()) site->setValidUntil(validUntil); auto_ptr_char id(site->getEntityID()); if (id.get()) { - m_sites.insert(make_pair(id.get(),site)); + if (replace) { + m_sites.erase(id.get()); + for (sitemap_t::iterator s = m_sources.begin(); s != m_sources.end();) { + if (s->second == site) { + sitemap_t::iterator temp = s; + ++s; + m_sources.erase(temp); + } + else { + ++s; + } + } + } + m_sites.insert(sitemap_t::value_type(id.get(),site)); } // Process each IdP role. @@ -90,7 +107,7 @@ void AbstractMetadataProvider::index(EntityDescriptor* site, time_t validUntil) if (sid) { auto_ptr_char sourceid(sid->getID()); if (sourceid.get()) { - m_sources.insert(pair(sourceid.get(),site)); + m_sources.insert(sitemap_t::value_type(sourceid.get(),site)); break; } } @@ -98,37 +115,33 @@ void AbstractMetadataProvider::index(EntityDescriptor* site, time_t validUntil) } // Hash the ID. - m_sources.insert( - pair(SAMLConfig::getConfig().hashSHA1(id.get(), true),site) - ); + m_sources.insert(sitemap_t::value_type(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)); // Load endpoints for type 0x0002 artifacts. const vector& locs=const_cast(*i)->getArtifactResolutionServices(); for (vector::const_iterator loc=locs.begin(); loc!=locs.end(); loc++) { auto_ptr_char location((*loc)->getLocation()); if (location.get()) - m_sources.insert(pair(location.get(),site)); + m_sources.insert(sitemap_t::value_type(location.get(),site)); } } // SAML 2.0? if ((*i)->hasSupport(samlconstants::SAML20P_NS)) { // Hash the ID. - m_sources.insert( - pair(SAMLConfig::getConfig().hashSHA1(id.get(), true),site) - ); + m_sources.insert(sitemap_t::value_type(SAMLConfig::getConfig().hashSHA1(id.get(), true),site)); } } } -void AbstractMetadataProvider::index(EntitiesDescriptor* group, time_t validUntil) +void AbstractMetadataProvider::index(EntitiesDescriptor* group, time_t validUntil) const { if (validUntil < group->getValidUntilEpoch()) group->setValidUntil(validUntil); auto_ptr_char name(group->getName()); if (name.get()) { - m_groups.insert(make_pair(name.get(),group)); + m_groups.insert(groupmap_t::value_type(name.get(),group)); } const vector& groups=const_cast(group)->getEntitiesDescriptors(); @@ -140,16 +153,18 @@ void AbstractMetadataProvider::index(EntitiesDescriptor* group, time_t validUnti index(*j,group->getValidUntilEpoch()); } -void AbstractMetadataProvider::clearDescriptorIndex() +void AbstractMetadataProvider::clearDescriptorIndex(bool freeSites) { - m_sources.clear(); + if (freeSites) + for_each(m_sites.begin(), m_sites.end(), cleanup_const_pair()); m_sites.clear(); m_groups.clear(); + m_sources.clear(); } const EntitiesDescriptor* AbstractMetadataProvider::getEntitiesDescriptor(const char* name, bool strict) const { - pair range=m_groups.equal_range(name); + pair range=const_cast(m_groups).equal_range(name); time_t now=time(NULL); for (groupmap_t::const_iterator i=range.first; i!=range.second; i++) @@ -162,29 +177,92 @@ const EntitiesDescriptor* AbstractMetadataProvider::getEntitiesDescriptor(const return NULL; } -const EntityDescriptor* AbstractMetadataProvider::getEntityDescriptor(const char* name, bool strict) const +pair AbstractMetadataProvider::getEntityDescriptor(const Criteria& criteria) const { - pair range=m_sites.equal_range(name); - + pair range; + if (criteria.entityID_ascii) + range = const_cast(m_sites).equal_range(criteria.entityID_ascii); + else if (criteria.entityID_unicode) { + auto_ptr_char id(criteria.entityID_unicode); + range = const_cast(m_sites).equal_range(id.get()); + } + else if (criteria.artifact) + range = const_cast(m_sources).equal_range(criteria.artifact->getSource()); + else + return pair(NULL,NULL); + + pair result; + result.first = NULL; + result.second = NULL; + time_t now=time(NULL); - for (sitemap_t::const_iterator i=range.first; i!=range.second; i++) - if (now < i->second->getValidUntilEpoch()) - return i->second; + for (sitemap_t::const_iterator i=range.first; i!=range.second; i++) { + if (now < i->second->getValidUntilEpoch()) { + result.first = i->second; + break; + } + } - if (!strict && range.first!=range.second) - return range.first->second; + if (!result.first && !criteria.validOnly && range.first!=range.second) + result.first = range.first->second; - return NULL; + if (result.first && criteria.role) { + result.second = result.first->getRoleDescriptor(*criteria.role, criteria.protocol); + if (!result.second && criteria.protocol2) + result.second = result.first->getRoleDescriptor(*criteria.role, criteria.protocol2); + } + + return result; } -const EntityDescriptor* AbstractMetadataProvider::getEntityDescriptor(const SAMLArtifact* artifact) const +const Credential* AbstractMetadataProvider::resolve(const CredentialCriteria* criteria) const { - pair range=m_sources.equal_range(artifact->getSource()); + const MetadataCredentialCriteria* metacrit = dynamic_cast(criteria); + if (!metacrit) + throw MetadataException("Cannot resolve credentials without a MetadataCredentialCriteria object."); - time_t now=time(NULL); - for (sitemap_t::const_iterator i=range.first; i!=range.second; i++) - if (now < i->second->getValidUntilEpoch()) - return i->second; + 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))) + return *c; return NULL; } + +vector::size_type AbstractMetadataProvider::resolve( + vector& results, const CredentialCriteria* criteria + ) const +{ + const MetadataCredentialCriteria* metacrit = dynamic_cast(criteria); + if (!metacrit) + throw MetadataException("Cannot resolve credentials without a MetadataCredentialCriteria object."); + + 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); + 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()) + return i->second; + + const KeyInfoResolver* resolver = m_resolver ? m_resolver : XMLToolingConfig::getConfig().getKeyInfoResolver(); + const vector& keys = role.getKeyDescriptors(); + AbstractMetadataProvider::credmap_t::mapped_type& resolved = m_credentialMap[&role]; + for (vector::const_iterator k = keys.begin(); k!=keys.end(); ++k) { + if ((*k)->getKeyInfo()) { + auto_ptr mcc(new MetadataCredentialContext(*(*k))); + Credential* c = resolver->resolve(mcc.get()); + mcc.release(); + resolved.push_back(c); + } + } + return resolved; +}