X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsecurity%2Fimpl%2FFilesystemCredentialResolver.cpp;h=70092144f88d553f4dc4f809f003602b7dc7965a;hb=a0d768778a8f5f539b909baf5b115e70ea765f0f;hp=541057e9347229e44940c5a6bcad08bd1dbe8201;hpb=ee4968e682f7031ad854f9d65ea6b5979a8b3505;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/security/impl/FilesystemCredentialResolver.cpp b/xmltooling/security/impl/FilesystemCredentialResolver.cpp index 541057e..7009214 100644 --- a/xmltooling/security/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/security/impl/FilesystemCredentialResolver.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,7 @@ #include "internal.h" #include "logging.h" +#include "io/HTTPResponse.h" #include "security/BasicX509Credential.h" #include "security/CredentialCriteria.h" #include "security/CredentialResolver.h" @@ -65,11 +66,14 @@ namespace xmltooling { SOAPTransport* getTransport() { SOAPTransport::Address addr("FilesystemCredentialResolver", source.c_str(), source.c_str()); string scheme(addr.m_endpoint, strchr(addr.m_endpoint,':') - addr.m_endpoint); - return XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr); + SOAPTransport* ret = XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr); + if (ret) + ret->setCacheTag(&cacheTag); + return ret; } public: - bool stale(Category& log, RWLock* lock=NULL) { + bool stale(Category& log, RWLock* lock=nullptr) { if (local) { #ifdef WIN32 struct _stat stat_buf; @@ -102,7 +106,7 @@ namespace xmltooling { log.info("change detected, reloading local resource..."); } else { - time_t now = time(NULL); + time_t now = time(nullptr); // Time to reload? if (now - filestamp < reloadInterval) @@ -129,18 +133,18 @@ namespace xmltooling { } bool local,reloadChanges; - string format,source,backing; + string format,source,backing,cacheTag; time_t filestamp,reloadInterval; }; class XMLTOOL_DLLLOCAL ManagedKey : public ManagedResource { public: - ManagedKey() : key(NULL) {} + ManagedKey() : key(nullptr) {} ~ManagedKey() { delete key; } void load(Category& log, const char* password) { if (source.empty()) return; - XSECCryptoKey* nkey=NULL; + XSECCryptoKey* nkey=nullptr; if (local) { nkey = SecurityHelper::loadKeyFromFile(source.c_str(), format.c_str(), password); } @@ -218,10 +222,10 @@ namespace xmltooling { m_lock->unlock(); } - const Credential* resolve(const CredentialCriteria* criteria=NULL) const; + const Credential* resolve(const CredentialCriteria* criteria=nullptr) const; virtual vector::size_type resolve( - vector& results, const CredentialCriteria* criteria=NULL + vector& results, const CredentialCriteria* criteria=nullptr ) const; private: @@ -254,7 +258,7 @@ namespace xmltooling { XSECCryptoKey* key, const vector& xseccerts, const vector& crls - ) : BasicX509Credential(key ? key : (xseccerts.empty() ? NULL : xseccerts.front()->clonePublicKey()), xseccerts, crls), m_resolver(resolver) { + ) : BasicX509Credential(key ? key : (xseccerts.empty() ? nullptr : xseccerts.front()->clonePublicKey()), xseccerts, crls), m_resolver(resolver) { if (m_resolver->m_extractNames) extract(); m_keyNames.insert(m_resolver->m_keynames.begin(), m_resolver->m_keynames.end()); @@ -308,7 +312,7 @@ namespace xmltooling { }; FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) - : m_lock(NULL), m_credential(NULL), m_usage(Credential::UNSPECIFIED_CREDENTIAL), m_extractNames(true) + : m_lock(nullptr), m_credential(nullptr), m_usage(Credential::UNSPECIFIED_CREDENTIAL), m_extractNames(true) { #ifdef _DEBUG NDC ndc("FilesystemCredentialResolver"); @@ -321,36 +325,36 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) Credential::KEYINFO_KEY_VALUE | X509Credential::KEYINFO_X509_CERTIFICATE | X509Credential::KEYINFO_X509_SUBJECTNAME; - if (e && e->hasAttributeNS(NULL,keyInfoMask)) - m_keyinfomask = XMLString::parseInt(e->getAttributeNS(NULL,keyInfoMask)); + if (e && e->hasAttributeNS(nullptr,keyInfoMask)) + m_keyinfomask = XMLString::parseInt(e->getAttributeNS(nullptr,keyInfoMask)); - if (e && (e->hasAttributeNS(NULL,_certificate) || e->hasAttributeNS(NULL,_key))) { + if (e && (e->hasAttributeNS(nullptr,_certificate) || e->hasAttributeNS(nullptr,_key))) { // Dummy up a simple file resolver config using these attributes. - DOMElement* dummy = e->getOwnerDocument()->createElementNS(NULL,_CredentialResolver); + DOMElement* dummy = e->getOwnerDocument()->createElementNS(nullptr,_CredentialResolver); DOMElement* child; DOMElement* path; - if (e->hasAttributeNS(NULL,_key)) { - child = e->getOwnerDocument()->createElementNS(NULL,Key); + if (e->hasAttributeNS(nullptr,_key)) { + child = e->getOwnerDocument()->createElementNS(nullptr,Key); dummy->appendChild(child); - path = e->getOwnerDocument()->createElementNS(NULL,Path); + path = e->getOwnerDocument()->createElementNS(nullptr,Path); child->appendChild(path); - path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,_key))); - if (e->hasAttributeNS(NULL,password)) - child->setAttributeNS(NULL,password,e->getAttributeNS(NULL,password)); - if (e->hasAttributeNS(NULL,keyName)) { - path = e->getOwnerDocument()->createElementNS(NULL,Name); + path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(nullptr,_key))); + if (e->hasAttributeNS(nullptr,password)) + child->setAttributeNS(nullptr,password,e->getAttributeNS(nullptr,password)); + if (e->hasAttributeNS(nullptr,keyName)) { + path = e->getOwnerDocument()->createElementNS(nullptr,Name); child->appendChild(path); - path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,keyName))); + path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(nullptr,keyName))); } } - if (e->hasAttributeNS(NULL,_certificate)) { - child = e->getOwnerDocument()->createElementNS(NULL,Certificate); + if (e->hasAttributeNS(nullptr,_certificate)) { + child = e->getOwnerDocument()->createElementNS(nullptr,Certificate); dummy->appendChild(child); - path = e->getOwnerDocument()->createElementNS(NULL,Path); + path = e->getOwnerDocument()->createElementNS(nullptr,Path); child->appendChild(path); - path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(NULL,_certificate))); - if (e->hasAttributeNS(NULL, extractNames)) - child->setAttributeNS(NULL, extractNames, e->getAttributeNS(NULL, extractNames)); + path->appendChild(e->getOwnerDocument()->createTextNode(e->getAttributeNS(nullptr,_certificate))); + if (e->hasAttributeNS(nullptr, extractNames)) + child->setAttributeNS(nullptr, extractNames, e->getAttributeNS(nullptr, extractNames)); } e = dummy; // reset "root" to the dummy config element } @@ -359,7 +363,7 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) const DOMElement* root = e; // Save off usage bits. - const XMLCh* usage = root->getAttributeNS(NULL,_use); + const XMLCh* usage = root->getAttributeNS(nullptr,_use); if (usage && *usage) { auto_ptr_char u(usage); if (!strcmp(u.get(), "signing")) @@ -373,13 +377,13 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) // Move to Key. const DOMElement* keynode = XMLHelper::getFirstChildElement(root,Key); if (keynode) { - prop = keynode->getAttributeNS(NULL,_format); + prop = keynode->getAttributeNS(nullptr,_format); if (prop && *prop) { auto_ptr_char f(prop); m_key.format = f.get(); } - prop = keynode->getAttributeNS(NULL,password); + prop = keynode->getAttributeNS(nullptr,password); if (prop && *prop) { auto_ptr_char kp(prop); m_keypass = kp.get(); @@ -391,7 +395,7 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) m_key.source = kpath.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(m_key.source, PathResolver::XMLTOOLING_CFG_FILE); m_key.local = true; - prop = e->getAttributeNS(NULL,_reloadChanges); + prop = e->getAttributeNS(nullptr,_reloadChanges); if (prop && (*prop==chLatin_f) || (*prop==chDigit_0)) m_key.reloadChanges = false; } @@ -400,13 +404,13 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) auto_ptr_char kpath(prop); m_key.source = kpath.get(); m_key.local = false; - prop = e->getAttributeNS(NULL,backingFilePath); + prop = e->getAttributeNS(nullptr,backingFilePath); if (!prop || !*prop) throw XMLSecurityException("FilesystemCredentialResolver can't access key, backingFilePath missing from URL element."); auto_ptr_char b(prop); m_key.backing = b.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(m_key.backing, PathResolver::XMLTOOLING_RUN_FILE); - prop = e->getAttributeNS(NULL,_reloadInterval); + prop = e->getAttributeNS(nullptr,_reloadInterval); if (prop && *prop) m_key.reloadInterval = XMLString::parseInt(prop); } @@ -429,7 +433,7 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) // Check for CRL. const DOMElement* crlnode = XMLHelper::getFirstChildElement(root,CRL); if (crlnode) { - const XMLCh* crlformat = crlnode->getAttributeNS(NULL,_format); + const XMLCh* crlformat = crlnode->getAttributeNS(nullptr,_format); e = XMLHelper::getFirstChildElement(crlnode,Path); while (e) { if (e->hasChildNodes()) { @@ -444,7 +448,7 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) crl.source = crlpath.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(crl.source, PathResolver::XMLTOOLING_CFG_FILE); crl.local = true; - prop = e->getAttributeNS(NULL,_reloadChanges); + prop = e->getAttributeNS(nullptr,_reloadChanges); if (prop && (*prop==chLatin_f) || (*prop==chDigit_0)) crl.reloadChanges = false; } @@ -464,13 +468,13 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) auto_ptr_char crlpath(prop); crl.source = crlpath.get(); crl.local = false; - prop = e->getAttributeNS(NULL,backingFilePath); + prop = e->getAttributeNS(nullptr,backingFilePath); if (!prop || !*prop) throw XMLSecurityException("FilesystemCredentialResolver can't access CRL, backingFilePath missing from URL element."); auto_ptr_char b(prop); crl.backing = b.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(crl.backing, PathResolver::XMLTOOLING_RUN_FILE); - prop = e->getAttributeNS(NULL,_reloadInterval); + prop = e->getAttributeNS(nullptr,_reloadInterval); if (prop && *prop) crl.reloadInterval = XMLString::parseInt(prop); } @@ -485,15 +489,15 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) // Check for Certificate DOMElement* certnode = XMLHelper::getFirstChildElement(root,Certificate); if (certnode) { - prop = certnode->getAttributeNS(NULL,password); + prop = certnode->getAttributeNS(nullptr,password); if (prop && *prop) { auto_ptr_char certpass(prop); m_certpass = certpass.get(); } - const XMLCh* certformat = certnode->getAttributeNS(NULL,_format); + const XMLCh* certformat = certnode->getAttributeNS(nullptr,_format); - const XMLCh* extractFlag = certnode->getAttributeNS(NULL, extractNames); + const XMLCh* extractFlag = certnode->getAttributeNS(nullptr, extractNames); if (extractFlag && (*extractFlag == chLatin_f || *extractFlag == chDigit_0)) m_extractNames = false; @@ -511,7 +515,7 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) cert.source = certpath.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(cert.source, PathResolver::XMLTOOLING_CFG_FILE); cert.local = true; - prop = e->getAttributeNS(NULL,_reloadChanges); + prop = e->getAttributeNS(nullptr,_reloadChanges); if (prop && (*prop==chLatin_f) || (*prop==chDigit_0)) cert.reloadChanges = false; } @@ -526,13 +530,13 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) auto_ptr_char certpath(prop); cert.source = certpath.get(); cert.local = false; - prop = e->getAttributeNS(NULL,backingFilePath); + prop = e->getAttributeNS(nullptr,backingFilePath); if (!prop || !*prop) throw XMLSecurityException("FilesystemCredentialResolver can't access certificate, backingFilePath missing from URL element."); auto_ptr_char b(prop); cert.backing = b.get(); XMLToolingConfig::getConfig().getPathResolver()->resolve(cert.backing, PathResolver::XMLTOOLING_RUN_FILE); - prop = e->getAttributeNS(NULL,_reloadInterval); + prop = e->getAttributeNS(nullptr,_reloadInterval); if (prop && *prop) cert.reloadInterval = XMLString::parseInt(prop); } @@ -546,11 +550,11 @@ FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) // Do an initial load of all the objects. If anything blows up here, whatever's // been loaded should be freed during teardown of the embedded objects. - time_t now = time(NULL); + time_t now = time(nullptr); m_key.filestamp = now; m_key.load(log, m_keypass.c_str()); for (vector::iterator i = m_certs.begin(); i != m_certs.end(); ++i) { - i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : NULL); + i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : nullptr); i->filestamp = now; } for (vector::iterator j = m_crls.begin(); j != m_crls.end(); ++j) { @@ -581,8 +585,8 @@ Credential* FilesystemCredentialResolver::getCredential() // We (unfortunately) need to duplicate all the objects and put them in one set of arrays // in order to create the credential wrapper. - FilesystemCredential* credential=NULL; - auto_ptr xseckey(m_key.key ? m_key.key->clone() : NULL); + FilesystemCredential* credential=nullptr; + auto_ptr xseckey(m_key.key ? m_key.key->clone() : nullptr); vector xseccerts; vector xseccrls; try { @@ -638,18 +642,36 @@ Lockable* FilesystemCredentialResolver::lock() m_key.load(log, m_keypass.c_str()); updated = true; } + catch (long& ex) { + if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { + log.info("remote key (%s) unchanged from cached version", m_key.source.c_str()); + } + else { + // Shouldn't happen, we should only get codes intended to be gracefully handled. + log.crit("maintaining existing key, remote fetch returned atypical status code (%d)", ex); + } + } catch (exception& ex) { log.crit("maintaining existing key: %s", ex.what()); } } for (vector::iterator i = m_certs.begin(); i != m_certs.end(); ++i) { - if (i->stale(log, writelock ? NULL : m_lock)) { + if (i->stale(log, writelock ? nullptr : m_lock)) { writelock = true; try { - i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : NULL); + i->load(log, (i==m_certs.begin()) ? m_certpass.c_str() : nullptr); updated = true; } + catch (long& ex) { + if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { + log.info("remote certificate(s) (%s) unchanged from cached version", i->source.c_str()); + } + else { + // Shouldn't happen, we should only get codes intended to be gracefully handled. + log.crit("maintaining existing certificate(s), remote fetch returned atypical status code (%d)", ex); + } + } catch (exception& ex) { log.crit("maintaining existing certificate(s): %s", ex.what()); } @@ -657,12 +679,21 @@ Lockable* FilesystemCredentialResolver::lock() } for (vector::iterator j = m_crls.begin(); j != m_crls.end(); ++j) { - if (j->stale(log, writelock ? NULL : m_lock)) { + if (j->stale(log, writelock ? nullptr : m_lock)) { writelock = true; try { j->load(log); updated = true; } + catch (long& ex) { + if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) { + log.info("remote CRL(s) (%s) unchanged from cached version", j->source.c_str()); + } + else { + // Shouldn't happen, we should only get codes intended to be gracefully handled. + log.crit("maintaining existing CRL(s), remote fetch returned atypical status code (%d)", ex); + } + } catch (exception& ex) { log.crit("maintaining existing CRL(s): %s", ex.what()); } @@ -689,7 +720,7 @@ Lockable* FilesystemCredentialResolver::lock() const Credential* FilesystemCredentialResolver::resolve(const CredentialCriteria* criteria) const { - return (criteria ? (criteria->matches(*m_credential) ? m_credential : NULL) : m_credential); + return (criteria ? (criteria->matches(*m_credential) ? m_credential : nullptr) : m_credential); } vector::size_type FilesystemCredentialResolver::resolve( @@ -742,11 +773,11 @@ void FilesystemCredential::attach(SSL_CTX* ctx) const else if (m_resolver->m_key.format == "PKCS12") { BIO* in=BIO_new(BIO_s_file_internal()); if (in && BIO_read_filename(in,path)>0) { - PKCS12* p12 = d2i_PKCS12_bio(in, NULL); + PKCS12* p12 = d2i_PKCS12_bio(in, nullptr); if (p12) { - EVP_PKEY* pkey=NULL; - X509* x=NULL; - PKCS12_parse(p12, const_cast(m_resolver->m_keypass.c_str()), &pkey, &x, NULL); + EVP_PKEY* pkey=nullptr; + X509* x=nullptr; + PKCS12_parse(p12, const_cast(m_resolver->m_keypass.c_str()), &pkey, &x, nullptr); PKCS12_free(p12); if (x) X509_free(x);