X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-opensaml.git;a=blobdiff_plain;f=saml%2Fsaml2%2Fmetadata%2Fimpl%2FDynamicMetadataProvider.cpp;h=47106ecdc1938bf350565917c730467d70285223;hp=4ccd536dd140165025302cb24efdcc5864a64fdd;hb=9247fd98448d17c495f1d811ac1ba82571f7ef98;hpb=807f7429a14b87055f56c6e7171ec7aae5def13f diff --git a/saml/saml2/metadata/impl/DynamicMetadataProvider.cpp b/saml/saml2/metadata/impl/DynamicMetadataProvider.cpp index 4ccd536..47106ec 100644 --- a/saml/saml2/metadata/impl/DynamicMetadataProvider.cpp +++ b/saml/saml2/metadata/impl/DynamicMetadataProvider.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Internet2 + * Copyright 2001-2009 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,10 +26,10 @@ #include "saml2/metadata/DynamicMetadataProvider.h" #include -#include #include #include #include +#include using namespace opensaml::saml2md; using namespace xmltooling::logging; @@ -53,13 +53,16 @@ namespace opensaml { }; DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e) - : AbstractMetadataProvider(e), m_maxCacheDuration(0), m_lock(RWLock::create()) + : AbstractMetadataProvider(e), m_maxCacheDuration(28800), m_lock(RWLock::create()) { const XMLCh* flag=e ? e->getAttributeNS(NULL,validate) : NULL; m_validate=(XMLString::equals(flag,xmlconstants::XML_TRUE) || XMLString::equals(flag,xmlconstants::XML_ONE)); flag = e ? e->getAttributeNS(NULL,maxCacheDuration) : NULL; - if (flag && *flag) + if (flag && *flag) { m_maxCacheDuration = XMLString::parseInt(flag); + if (m_maxCacheDuration == 0) + m_maxCacheDuration = 28800; + } } DynamicMetadataProvider::~DynamicMetadataProvider() @@ -83,49 +86,96 @@ pair DynamicMetadataProvider::get auto_ptr_char temp(criteria.entityID_unicode); name = temp.get(); } - else if (criteria.artifact) + else if (criteria.artifact) { name = criteria.artifact->getSource(); + } else return entity; Category& log = Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic"); log.info("resolving metadata for (%s)", name.c_str()); - // Try resolving it. - auto_ptr entity2(resolve(name.c_str())); + try { + // Try resolving it. + auto_ptr entity2(resolve(criteria)); - // Filter it, which may throw. - doFilters(*entity2.get()); + // Verify the entityID. + if (criteria.entityID_unicode && !XMLString::equals(criteria.entityID_unicode, entity2->getEntityID())) { + log.error("metadata instance did not match expected entityID"); + return entity; + } + else { + auto_ptr_XMLCh temp2(name.c_str()); + if (!XMLString::equals(temp2.get(), entity2->getEntityID())) { + log.error("metadata instance did not match expected entityID"); + return entity; + } + } + + if (!m_validate) { + try { + SchemaValidators.validate(entity2.get()); + } + catch (exception& ex) { + log.error("metadata intance failed manual schema validation checking: %s", ex.what()); + throw MetadataException("Metadata instance failed manual schema validation checking."); + } + } - log.info("caching resolved metadata for (%s)", name.c_str()); + // Filter it, which may throw. + doFilters(*entity2.get()); - // Translate cacheDuration into validUntil. - if (entity2->getCacheDuration()) - entity2->setValidUntil(time(NULL) + min(m_maxCacheDuration, entity2->getCacheDurationEpoch())); + time_t now = time(NULL); - // Upgrade our lock so we can cache the new metadata. - m_lock->unlock(); - m_lock->wrlock(); + if (entity2->getValidUntil() && entity2->getValidUntilEpoch() < now + 60) + throw MetadataException("Metadata was already invalid at the time of retrieval."); - // Notify observers. - emitChangeEvent(); + log.info("caching resolved metadata for (%s)", name.c_str()); - // Make sure we clear out any existing copies, including stale metadata or if somebody snuck in. - index(entity2.release(), SAMLTIME_MAX, true); + // Upgrade our lock so we can cache the new metadata. + m_lock->unlock(); + m_lock->wrlock(); - // Downgrade back to a read lock. - m_lock->unlock(); - m_lock->rdlock(); + // Notify observers. + emitChangeEvent(); + + // Make sure we clear out any existing copies, including stale metadata or if somebody snuck in. + time_t exp = m_maxCacheDuration; + if (entity2->getCacheDuration()) + exp = min(m_maxCacheDuration, entity2->getCacheDurationEpoch()); + exp += now; + index(entity2.release(), exp, true); + + // Downgrade back to a read lock. + m_lock->unlock(); + m_lock->rdlock(); + } + catch (exception& e) { + log.error("error while resolving entityID (%s): %s", name.c_str(), e.what()); + return entity; + } // Rinse and repeat. return getEntityDescriptor(criteria); } -EntityDescriptor* DynamicMetadataProvider::resolve(const char* entityID) const +EntityDescriptor* DynamicMetadataProvider::resolve(const Criteria& criteria) const { + string name; + if (criteria.entityID_ascii) { + name = criteria.entityID_ascii; + } + else if (criteria.entityID_unicode) { + auto_ptr_char temp(criteria.entityID_unicode); + name = temp.get(); + } + else if (criteria.artifact) { + throw MetadataException("Unable to resolve metadata dynamically from an artifact."); + } + try { DOMDocument* doc=NULL; - auto_ptr_XMLCh widenit(entityID); + auto_ptr_XMLCh widenit(name.c_str()); URLInputSource src(widenit.get()); Wrapper4InputSource dsrc(&src,false); if (m_validate) @@ -153,14 +203,8 @@ EntityDescriptor* DynamicMetadataProvider::resolve(const char* entityID) const catch (XMLException& e) { auto_ptr_char msg(e.getMessage()); Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic").error( - "Xerces error while resolving entityID (%s): %s", entityID, msg.get() + "Xerces error while resolving entityID (%s): %s", name.c_str(), msg.get() ); throw MetadataException(msg.get()); } - catch (exception& e) { - Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic").error( - "error while resolving entityID (%s): %s", entityID, e.what() - ); - throw; - } }