X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Futil%2FReloadableXMLFile.cpp;h=ae5f5be121b6a164d3a36a1cadc1b62606852eab;hb=5c58bb4be90a1615d0f4252067fb42851d3f123d;hp=03a8c90a7b56a94c4bdeda87006fde2711497ade;hpb=04302f1b6d2b753b00ff2bb99b20a89488f2f13d;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/util/ReloadableXMLFile.cpp b/xmltooling/util/ReloadableXMLFile.cpp index 03a8c90..ae5f5be 100644 --- a/xmltooling/util/ReloadableXMLFile.cpp +++ b/xmltooling/util/ReloadableXMLFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 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. @@ -22,6 +22,14 @@ #include "internal.h" #include "io/HTTPResponse.h" +#ifndef XMLTOOLING_LITE +# include "security/Credential.h" +# include "security/CredentialCriteria.h" +# include "security/CredentialResolver.h" +# include "security/SignatureTrustEngine.h" +# include "signature/Signature.h" +# include "signature/SignatureValidator.h" +#endif #include "util/NDC.h" #include "util/PathResolver.h" #include "util/ReloadableXMLFile.h" @@ -29,6 +37,13 @@ #include "util/XMLConstants.h" #include "util/XMLHelper.h" +#if defined(XMLTOOLING_LOG4SHIB) +# include +#elif defined(XMLTOOLING_LOG4CPP) +# include +#endif + +#include #include #include #include @@ -37,11 +52,37 @@ #include #include +#ifndef XMLTOOLING_LITE +# include +# include +using namespace xmlsignature; +#endif + using namespace xmltooling::logging; using namespace xmltooling; using namespace xercesc; using namespace std; +#ifndef XMLTOOLING_LITE +namespace { + class XMLTOOL_DLLLOCAL DummyCredentialResolver : public CredentialResolver + { + public: + DummyCredentialResolver() {} + ~DummyCredentialResolver() {} + + Lockable* lock() {return this;} + void unlock() {} + + const Credential* resolve(const CredentialCriteria* criteria=nullptr) const {return nullptr;} + vector::size_type resolve( + vector& results, const CredentialCriteria* criteria=nullptr + ) const {return 0;} + }; +}; +#endif + +static const XMLCh id[] = UNICODE_LITERAL_2(i,d); static const XMLCh uri[] = UNICODE_LITERAL_3(u,r,i); static const XMLCh url[] = UNICODE_LITERAL_3(u,r,l); static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); @@ -51,60 +92,95 @@ static const XMLCh filename[] = UNICODE_LITERAL_8(f,i,l,e,n,a,m,e); static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); static const XMLCh reloadChanges[] = UNICODE_LITERAL_13(r,e,l,o,a,d,C,h,a,n,g,e,s); static const XMLCh reloadInterval[] = UNICODE_LITERAL_14(r,e,l,o,a,d,I,n,t,e,r,v,a,l); +static const XMLCh maxRefreshDelay[] = UNICODE_LITERAL_15(m,a,x,R,e,f,r,e,s,h,D,e,l,a,y); static const XMLCh backingFilePath[] = UNICODE_LITERAL_15(b,a,c,k,i,n,g,F,i,l,e,P,a,t,h); - - -ReloadableXMLFile::~ReloadableXMLFile() -{ - delete m_lock; -} - -ReloadableXMLFile::ReloadableXMLFile(const DOMElement* e, Category& log) - : m_root(e), m_local(true), m_validate(false), m_filestamp(0), m_reloadInterval(0), m_lock(NULL), m_log(log) +static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e); +static const XMLCh certificate[] = UNICODE_LITERAL_11(c,e,r,t,i,f,i,c,a,t,e); +static const XMLCh signerName[] = UNICODE_LITERAL_10(s,i,g,n,e,r,N,a,m,e); +static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e); +static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r); + + +ReloadableXMLFile::ReloadableXMLFile(const DOMElement* e, Category& log, bool startReloadThread) + : m_root(e), m_local(true), m_validate(false), m_filestamp(0), m_reloadInterval(0), + m_lock(nullptr), m_log(log), m_loaded(false), +#ifndef XMLTOOLING_LITE + m_credResolver(nullptr), m_trust(nullptr), +#endif + m_shutdown(false), m_reload_wait(nullptr), m_reload_thread(nullptr) { #ifdef _DEBUG NDC ndc("ReloadableXMLFile"); #endif // Establish source of data... - const XMLCh* source=e->getAttributeNS(NULL,uri); + const XMLCh* source=e->getAttributeNS(nullptr,uri); if (!source || !*source) { - source=e->getAttributeNS(NULL,url); + source=e->getAttributeNS(nullptr,url); if (!source || !*source) { - source=e->getAttributeNS(NULL,path); + source=e->getAttributeNS(nullptr,path); if (!source || !*source) { - source=e->getAttributeNS(NULL,pathname); + source=e->getAttributeNS(nullptr,pathname); if (!source || !*source) { - source=e->getAttributeNS(NULL,file); + source=e->getAttributeNS(nullptr,file); if (!source || !*source) { - source=e->getAttributeNS(NULL,filename); + source=e->getAttributeNS(nullptr,filename); } } } } - else + else { m_local=false; + } } - else + else { m_local=false; + } if (source && *source) { - const XMLCh* flag=e->getAttributeNS(NULL,validate); - m_validate=(XMLString::equals(flag,xmlconstants::XML_TRUE) || XMLString::equals(flag,xmlconstants::XML_ONE)); + m_validate = XMLHelper::getAttrBool(e, false, validate); auto_ptr_char temp(source); - m_source=temp.get(); + m_source = temp.get(); if (!m_local && !strstr(m_source.c_str(),"://")) { log.warn("deprecated usage of uri/url attribute for a local resource, use path instead"); - m_local=true; + m_local = true; } +#ifndef XMLTOOLING_LITE + // Check for signature bits. + if (e->hasAttributeNS(nullptr, certificate)) { + // Use a file-based credential resolver rooted here. + m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(FILESYSTEM_CREDENTIAL_RESOLVER, e); + } + else { + const DOMElement* sub = XMLHelper::getFirstChildElement(e, _CredentialResolver); + string t(XMLHelper::getAttrString(sub, nullptr, type)); + if (!t.empty()) { + m_credResolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(t.c_str(), sub); + } + else { + sub = XMLHelper::getFirstChildElement(e, _TrustEngine); + t = XMLHelper::getAttrString(sub, nullptr, type); + if (!t.empty()) { + TrustEngine* trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), sub); + if (!(m_trust = dynamic_cast(trust))) { + delete trust; + throw XMLToolingException("TrustEngine-based ReloadableXMLFile requires a SignatureTrustEngine plugin."); + } + + m_signerName = XMLHelper::getAttrString(e, nullptr, signerName); + } + } + } +#endif + if (m_local) { XMLToolingConfig::getConfig().getPathResolver()->resolve(m_source, PathResolver::XMLTOOLING_CFG_FILE); - flag=e->getAttributeNS(NULL,reloadChanges); - if (!XMLString::equals(flag,xmlconstants::XML_FALSE) && !XMLString::equals(flag,xmlconstants::XML_ZERO)) { + bool flag = XMLHelper::getAttrBool(e, true, reloadChanges); + if (flag) { #ifdef WIN32 struct _stat stat_buf; if (_stat(m_source.c_str(), &stat_buf) == 0) @@ -112,70 +188,234 @@ ReloadableXMLFile::ReloadableXMLFile(const DOMElement* e, Category& log) struct stat stat_buf; if (stat(m_source.c_str(), &stat_buf) == 0) #endif - m_filestamp=stat_buf.st_mtime; + m_filestamp = stat_buf.st_mtime; else throw IOException("Unable to access local file ($1)", params(1,m_source.c_str())); - m_lock=RWLock::create(); + m_lock = RWLock::create(); } log.debug("using local resource (%s), will %smonitor for changes", m_source.c_str(), m_lock ? "" : "not "); } else { log.debug("using remote resource (%s)", m_source.c_str()); - source = e->getAttributeNS(NULL,backingFilePath); - if (source && *source) { - auto_ptr_char temp2(source); - m_backing=temp2.get(); + m_backing = XMLHelper::getAttrString(e, nullptr, backingFilePath); + if (!m_backing.empty()) { XMLToolingConfig::getConfig().getPathResolver()->resolve(m_backing, PathResolver::XMLTOOLING_RUN_FILE); - log.debug("backup remote resource with (%s)", m_backing.c_str()); - } - source = e->getAttributeNS(NULL,reloadInterval); - if (source && *source) { - m_reloadInterval = XMLString::parseInt(source); - if (m_reloadInterval > 0) { - m_log.debug("will reload remote resource at most every %d seconds", m_reloadInterval); - m_lock=RWLock::create(); + log.debug("backup remote resource to (%s)", m_backing.c_str()); + try { + string tagname = m_backing + ".tag"; + ifstream backer(tagname.c_str()); + if (backer) { + char cachebuf[256]; + if (backer.getline(cachebuf, 255)) { + m_cacheTag = cachebuf; + log.debug("loaded initial cache tag (%s)", m_cacheTag.c_str()); + } + } } + catch (exception&) { + } + } + m_reloadInterval = XMLHelper::getAttrInt(e, 0, reloadInterval); + if (m_reloadInterval == 0) + m_reloadInterval = XMLHelper::getAttrInt(e, 0, maxRefreshDelay); + if (m_reloadInterval > 0) { + m_log.debug("will reload remote resource at most every %d seconds", m_reloadInterval); + m_lock = RWLock::create(); } - m_filestamp = time(NULL); // assume it gets loaded initially + m_filestamp = time(nullptr); // assume it gets loaded initially } + + if (startReloadThread) + startup(); } else { log.debug("no resource uri/path/name supplied, will load inline configuration"); } + + m_id = XMLHelper::getAttrString(e, nullptr, id); +} + +ReloadableXMLFile::~ReloadableXMLFile() +{ + shutdown(); + delete m_lock; +} + +void ReloadableXMLFile::startup() +{ + if (m_lock && !m_reload_thread) { + m_reload_wait = CondWait::create(); + m_reload_thread = Thread::create(&reload_fn, this); + } +} + +void ReloadableXMLFile::shutdown() +{ + if (m_reload_thread) { + // Shut down the reload thread and let it know. + m_shutdown = true; + m_reload_wait->signal(); + m_reload_thread->join(nullptr); + delete m_reload_thread; + delete m_reload_wait; + m_reload_thread = nullptr; + m_reload_wait = nullptr; + } +} + +void* ReloadableXMLFile::reload_fn(void* pv) +{ + ReloadableXMLFile* r = reinterpret_cast(pv); + +#ifndef WIN32 + // First, let's block all signals + Thread::mask_all_signals(); +#endif + + if (!r->m_id.empty()) { + string threadid("["); + threadid += r->m_id + ']'; + logging::NDC::push(threadid); + } + +#ifdef _DEBUG + NDC ndc("reload"); +#endif + + auto_ptr mutex(Mutex::create()); + mutex->lock(); + + if (r->m_local) + r->m_log.info("reload thread started...running when signaled"); + else + r->m_log.info("reload thread started...running every %d seconds", r->m_reloadInterval); + + while (!r->m_shutdown) { + if (r->m_local) + r->m_reload_wait->wait(mutex.get()); + else + r->m_reload_wait->timedwait(mutex.get(), r->m_reloadInterval); + if (r->m_shutdown) + break; + + try { + r->m_log.info("reloading %s resource...", r->m_local ? "local" : "remote"); + pair ret = r->background_load(); + if (ret.first) + ret.second->getOwnerDocument()->release(); + } + catch (long& ex) { + if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { + r->m_log.info("remote resource (%s) unchanged from cached version", r->m_source.c_str()); + } + else { + // Shouldn't happen, we should only get codes intended to be gracefully handled. + r->m_log.crit("maintaining existing configuration, remote resource fetch returned atypical status code (%d)", ex); + } + } + catch (exception& ex) { + r->m_log.crit("maintaining existing configuration, error reloading resource (%s): %s", r->m_source.c_str(), ex.what()); + } + } + + r->m_log.info("reload thread finished"); + + mutex->unlock(); + + if (!r->m_id.empty()) { + logging::NDC::pop(); + } + + return nullptr; +} + +Lockable* ReloadableXMLFile::lock() +{ + if (!m_lock) + return this; + + m_lock->rdlock(); + + if (m_local) { + // Check if we need to refresh. +#ifdef WIN32 + struct _stat stat_buf; + if (_stat(m_source.c_str(), &stat_buf) != 0) + return this; +#else + struct stat stat_buf; + if (stat(m_source.c_str(), &stat_buf) != 0) + return this; +#endif + if (m_filestamp >= stat_buf.st_mtime) + return this; + + // Elevate lock and recheck. + m_log.debug("timestamp of local resource changed, elevating to a write lock"); + m_lock->unlock(); + m_lock->wrlock(); + if (m_filestamp >= stat_buf.st_mtime) { + // Somebody else handled it, just downgrade. + m_log.debug("update of local resource handled by another thread, downgrading lock"); + m_lock->unlock(); + m_lock->rdlock(); + return this; + } + + // Update the timestamp regardless. + m_filestamp = stat_buf.st_mtime; + if (m_reload_wait) { + m_log.info("change detected, signaling reload thread..."); + m_reload_wait->signal(); + } + else { + m_log.warn("change detected, but reload thread not started"); + } + } + + return this; +} + +void ReloadableXMLFile::unlock() +{ + if (m_lock) + m_lock->unlock(); } pair ReloadableXMLFile::load(bool backup) { #ifdef _DEBUG - NDC ndc("init"); + NDC ndc("load"); #endif try { if (m_source.empty()) { // Data comes from the DOM we were handed. m_log.debug("loading inline configuration..."); - return make_pair(false,XMLHelper::getFirstChildElement(m_root)); + return make_pair(false, XMLHelper::getFirstChildElement(m_root)); } else { // Data comes from a file we have to parse. if (backup) - m_log.warn("using local backup of remote resource"); + m_log.info("using local backup of remote resource"); else m_log.debug("loading configuration from external resource..."); - DOMDocument* doc=NULL; + DOMDocument* doc=nullptr; if (m_local || backup) { auto_ptr_XMLCh widenit(backup ? m_backing.c_str() : m_source.c_str()); + // Use library-wide lock for now, nothing else is using it anyway. + Locker locker(backup ? getBackupLock() : nullptr); LocalFileInputSource src(widenit.get()); - Wrapper4InputSource dsrc(&src,false); + Wrapper4InputSource dsrc(&src, false); if (m_validate) doc=XMLToolingConfig::getConfig().getValidatingParser().parse(dsrc); else doc=XMLToolingConfig::getConfig().getParser().parse(dsrc); } else { - URLInputSource src(m_root, NULL, &m_cacheTag); - Wrapper4InputSource dsrc(&src,false); + URLInputSource src(m_root, nullptr, &m_cacheTag); + Wrapper4InputSource dsrc(&src, false); if (m_validate) doc=XMLToolingConfig::getConfig().getValidatingParser().parse(dsrc); else @@ -185,9 +425,8 @@ pair ReloadableXMLFile::load(bool backup) if (XMLHelper::isNodeNamed(doc->getDocumentElement(), xmlconstants::XMLTOOLING_NS, URLInputSource::utf16StatusCodeElementName)) { int responseCode = XMLString::parseInt(doc->getDocumentElement()->getFirstChild()->getNodeValue()); doc->release(); - if (responseCode == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { - throw responseCode; // toss out as a "known" case to handle gracefully - } + if (responseCode == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) + throw (long)responseCode; // toss out as a "known" case to handle gracefully else { m_log.warn("remote resource fetch returned atypical status code (%d)", responseCode); throw IOException("remote resource fetch failed, check log for status code of response"); @@ -196,133 +435,183 @@ pair ReloadableXMLFile::load(bool backup) } m_log.infoStream() << "loaded XML resource (" << (backup ? m_backing : m_source) << ")" << logging::eol; - - if (!backup && !m_backing.empty()) { - m_log.debug("backing up remote resource to (%s)", m_backing.c_str()); +#ifndef XMLTOOLING_LITE + if (m_credResolver || m_trust) { + m_log.debug("checking signature on XML resource"); try { - ofstream backer(m_backing.c_str()); - backer << *doc; + DOMElement* sigel = XMLHelper::getFirstChildElement(doc->getDocumentElement(), xmlconstants::XMLSIG_NS, Signature::LOCAL_NAME); + if (!sigel) + throw XMLSecurityException("Signature validation required, but no signature found."); + + // Wrap and unmarshall the signature for the duration of the check. + auto_ptr sigobj(dynamic_cast(SignatureBuilder::buildOneFromElement(sigel))); // don't bind to document + validateSignature(*sigobj.get()); } - catch (exception& ex) { - m_log.crit("exception while backing up resource: %s", ex.what()); + catch (exception&) { + doc->release(); + throw; } - } - return make_pair(true,doc->getDocumentElement()); + } +#endif + return make_pair(true, doc->getDocumentElement()); } } catch (XMLException& e) { auto_ptr_char msg(e.getMessage()); m_log.errorStream() << "Xerces error while loading resource (" << (backup ? m_backing : m_source) << "): " << msg.get() << logging::eol; - if (!backup && !m_backing.empty()) - return load(true); throw XMLParserException(msg.get()); } catch (exception& e) { m_log.errorStream() << "error while loading resource (" << (m_source.empty() ? "inline" : (backup ? m_backing : m_source)) << "): " << e.what() << logging::eol; - if (!backup && !m_backing.empty()) - return load(true); throw; } } -Lockable* ReloadableXMLFile::lock() +pair ReloadableXMLFile::load() { - if (!m_lock) - return this; + // If this method is used, we're responsible for managing failover to a + // backup of a remote resource (if available), and for backing up remote + // resources. + try { + pair ret = load(false); + if (!m_backing.empty()) { + m_log.debug("backing up remote resource to (%s)", m_backing.c_str()); + try { + Locker locker(getBackupLock()); + ofstream backer(m_backing.c_str()); + backer << *(ret.second->getOwnerDocument()); + preserveCacheTag(); + } + catch (exception& ex) { + m_log.crit("exception while backing up resource: %s", ex.what()); + } + } + return ret; + } + catch (long& responseCode) { + // If there's an HTTP error or the document hasn't changed, + // use the backup iff we have no "valid" resource in place. + // That prevents reload of the backup copy any time the document + // hasn't changed. + if (responseCode == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) + m_log.info("remote resource (%s) unchanged from cached version", m_source.c_str()); + if (!m_loaded && !m_backing.empty()) + return load(true); + throw; + } + catch (exception&) { + // Same as above, but for general load/parse errors. + if (!m_loaded && !m_backing.empty()) + return load(true); + throw; + } +} - m_lock->rdlock(); +pair ReloadableXMLFile::background_load() +{ + // If this method isn't overridden, we acquire a write lock + // and just call the old override. + if (m_lock) + m_lock->wrlock(); + SharedLock locker(m_lock, false); + return load(); +} - // Check if we need to refresh. - if (m_local) { -#ifdef WIN32 - struct _stat stat_buf; - if (_stat(m_source.c_str(), &stat_buf) != 0) - return this; -#else - struct stat stat_buf; - if (stat(m_source.c_str(), &stat_buf) != 0) - return this; -#endif - if (m_filestamp>=stat_buf.st_mtime) - return this; +Lockable* ReloadableXMLFile::getBackupLock() +{ + return &XMLToolingConfig::getConfig(); +} - // Elevate lock and recheck. - m_log.debug("timestamp of local resource changed, elevating to a write lock"); - m_lock->unlock(); - m_lock->wrlock(); - if (m_filestamp>=stat_buf.st_mtime) { - // Somebody else handled it, just downgrade. - m_log.debug("update of local resource handled by another thread, downgrading lock"); - m_lock->unlock(); - m_lock->rdlock(); - return this; +void ReloadableXMLFile::preserveCacheTag() +{ + if (!m_cacheTag.empty() && !m_backing.empty()) { + try { + string tagname = m_backing + ".tag"; + ofstream backer(tagname.c_str()); + backer << m_cacheTag; + } + catch (exception&) { } - - // Update the timestamp regardless. No point in repeatedly trying. - m_filestamp=stat_buf.st_mtime; - m_log.info("change detected, reloading local resource..."); } - else { - time_t now = time(NULL); +} - // Time to reload? If we have no data, filestamp is zero - // and there's no way current time is less than the interval. - if (now - m_filestamp < m_reloadInterval) - return this; +#ifndef XMLTOOLING_LITE - // Elevate lock and recheck. - m_log.debug("reload interval for remote resource elapsed, elevating to a write lock"); - m_lock->unlock(); - m_lock->wrlock(); - if (now - m_filestamp < m_reloadInterval) { - // Somebody else handled it, just downgrade. - m_log.debug("update of remote resource handled by another thread, downgrading lock"); - m_lock->unlock(); - m_lock->rdlock(); - return this; +void ReloadableXMLFile::validateSignature(Signature& sigObj) const +{ + DSIGSignature* sig=sigObj.getXMLSignature(); + if (!sig) + throw XMLSecurityException("Signature does not exist yet."); + + // Make sure the whole document was signed. + bool valid=false; + DSIGReferenceList* refs=sig->getReferenceList(); + if (refs && refs->getSize()==1) { + DSIGReference* ref=refs->item(0); + if (ref) { + const XMLCh* URI=ref->getURI(); + if (URI==nullptr || *URI==0) { + DSIGTransformList* tlist=ref->getTransforms(); + if (tlist->getSize() <= 2) { + for (unsigned int i=0; tlist && igetSize(); i++) { + if (tlist->item(i)->getTransformType()==TRANSFORM_ENVELOPED_SIGNATURE) + valid=true; + else if (tlist->item(i)->getTransformType()!=TRANSFORM_EXC_C14N && + tlist->item(i)->getTransformType()!=TRANSFORM_C14N +#ifdef XMLTOOLING_XMLSEC_C14N11 + && tlist->item(i)->getTransformType()!=TRANSFORM_C14N11 +#endif + ) { + valid=false; + break; + } + } + } + } } - - m_filestamp = now; - m_log.info("reloading remote resource..."); } - - // Do this once... - try { - // At this point we're holding the write lock, so make sure we pop it. - SharedLock lockwrap(m_lock,false); - pair ret=load(); - if (ret.first) - ret.second->getOwnerDocument()->release(); - } - catch (int& ex) { - if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { - m_log.info("remote resource (%s) unchanged from cached version", m_source.c_str()); + + if (!valid) + throw XMLSecurityException("Invalid signature profile for signed configuration resource."); + + // Set up criteria. + CredentialCriteria cc; + cc.setUsage(Credential::SIGNING_CREDENTIAL); + cc.setSignature(sigObj, CredentialCriteria::KEYINFO_EXTRACTION_KEY); + if (!m_signerName.empty()) + cc.setPeerName(m_signerName.c_str()); + + if (m_credResolver) { + Locker locker(m_credResolver); + vector creds; + if (m_credResolver->resolve(creds, &cc)) { + SignatureValidator sigValidator; + for (vector::const_iterator i = creds.begin(); i != creds.end(); ++i) { + try { + sigValidator.setCredential(*i); + sigValidator.validate(&sigObj); + return; // success! + } + catch (exception&) { + } + } + throw XMLSecurityException("Unable to verify signature with supplied key(s)."); } else { - // Shouldn't happen, we should only get codes intended to be gracefully handled. - m_log.crit("maintaining existing configuration, remote resource fetch returned atypical status code (%d)", ex); + throw XMLSecurityException("CredentialResolver did not supply any candidate keys."); } } - catch (exception& ex) { - m_log.crit("maintaining existing configuration, error reloading resource (%s): %s", m_source.c_str(), ex.what()); + else if (m_trust) { + DummyCredentialResolver dummy; + if (m_trust->validate(sigObj, dummy, &cc)) + return; + throw XMLSecurityException("TrustEngine unable to verify signature."); } - // If we made it here, the swap may or may not have worked, but we need to relock. - m_log.debug("attempt to update resource complete, relocking"); - m_lock->rdlock(); - return this; + throw XMLSecurityException("Unable to verify signature."); } -void ReloadableXMLFile::unlock() -{ - if (m_lock) - m_lock->unlock(); -} - -pair ReloadableXMLFile::load() -{ - return load(false); -} +#endif