From 595b07cd612b3a1241eccf52553aa97b8d0c3e2e Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Wed, 31 Mar 2010 21:51:07 +0000 Subject: [PATCH] Multi-line svn commit, see body. https://issues.shibboleth.net/jira/browse/CPPOST-44 https://issues.shibboleth.net/jira/browse/CPPOST-45 --- saml/saml2/metadata/impl/XMLMetadataProvider.cpp | 68 ++++++++++++++++++------ 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/saml/saml2/metadata/impl/XMLMetadataProvider.cpp b/saml/saml2/metadata/impl/XMLMetadataProvider.cpp index 0dbc9c7..9c1c6b6 100644 --- a/saml/saml2/metadata/impl/XMLMetadataProvider.cpp +++ b/saml/saml2/metadata/impl/XMLMetadataProvider.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Internet2 + * 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. @@ -21,12 +21,15 @@ */ #include "internal.h" +#include "binding/SAMLArtifact.h" #include "saml2/metadata/Metadata.h" #include "saml2/metadata/MetadataFilter.h" #include "saml2/metadata/AbstractMetadataProvider.h" +#include #include #include +#include #include using namespace opensaml::saml2md; @@ -54,7 +57,7 @@ namespace opensaml { } void init() { - load(); // guarantees an exception or the metadata is loaded + background_load(); // guarantees an exception or the metadata is loaded } const XMLObject* getMetadata() const { @@ -62,7 +65,7 @@ namespace opensaml { } protected: - pair load(); + pair background_load(); private: using AbstractMetadataProvider::index; @@ -84,8 +87,11 @@ namespace opensaml { #pragma warning( pop ) #endif -pair XMLMetadataProvider::load() +pair XMLMetadataProvider::background_load() { + // Turn off auto-backup so we can filter first. + m_backupIndicator = false; + // Load from source using base class. pair raw = ReloadableXMLFile::load(); @@ -110,11 +116,48 @@ pair XMLMetadataProvider::load() throw MetadataException("Metadata instance failed manual validation checking."); } - doFilters(*xmlObject.get()); + // If the backup indicator is flipped, then this was a remote load and we need a backup. + // This is the best place to take a backup, since it's superficially "correct" metadata. + string backupKey; + if (m_backupIndicator) { + // We compute a random filename extension to the "real" location. + SAMLConfig::getConfig().generateRandomBytes(backupKey, 2); + backupKey = m_backing + '.' + SAMLArtifact::toHex(backupKey); + m_log.debug("backing up remote metadata resource to (%s)", backupKey.c_str()); + try { + ofstream backer(backupKey.c_str()); + backer << *raw.second->getOwnerDocument(); + } + catch (exception& ex) { + m_log.crit("exception while backing up metadata: %s", ex.what()); + backupKey.erase(); + } + } + + try { + doFilters(*xmlObject.get()); + } + catch (exception&) { + if (!backupKey.empty()) + remove(backupKey.c_str()); + throw; + } + + if (!backupKey.empty()) { + m_log.debug("committing backup file to permanent location (%s)", m_backing.c_str()); + Locker locker(getBackupLock()); + remove(m_backing.c_str()); + if (rename(backupKey.c_str(), m_backing.c_str()) != 0) + m_log.crit("unable to rename metadata backup file"); + } + xmlObject->releaseThisAndChildrenDOM(); xmlObject->setDocument(NULL); - // Swap it in. + // Swap it in after acquiring write lock if necessary. + if (m_lock) + m_lock->wrlock(); + SharedLock locker(m_lock, false); bool changed = m_object!=NULL; delete m_object; m_object = xmlObject.release(); @@ -122,7 +165,7 @@ pair XMLMetadataProvider::load() if (changed) emitChangeEvent(); - // If a remote resource, reduce the reload interval if cacheDuration is set. + // If a remote resource, adjust the reload interval if cacheDuration is set. if (!m_local) { const CacheableSAMLObject* cacheable = dynamic_cast(m_object); if (cacheable && cacheable->getCacheDuration() && cacheable->getCacheDurationEpoch() < m_maxCacheDuration) @@ -136,18 +179,11 @@ pair XMLMetadataProvider::load() void XMLMetadataProvider::index() { - time_t exp = SAMLTIME_MAX; - clearDescriptorIndex(); EntitiesDescriptor* group=dynamic_cast(m_object); if (group) { - if (!m_local && group->getCacheDuration()) - exp = time(NULL) + group->getCacheDurationEpoch(); - AbstractMetadataProvider::index(group, exp); + AbstractMetadataProvider::index(group, SAMLTIME_MAX); return; } - EntityDescriptor* site=dynamic_cast(m_object); - if (!m_local && site->getCacheDuration()) - exp = time(NULL) + site->getCacheDurationEpoch(); - AbstractMetadataProvider::index(site, exp); + AbstractMetadataProvider::index(dynamic_cast(m_object), SAMLTIME_MAX); } -- 2.1.4